<%

' -----------------------------------------------------------------
' Page Class
'
Class cxwlm_grid

	' Page ID
	Public Property Get PageID()
		PageID = "grid"
	End Property

	' Project ID
	Public Property Get ProjectID()
		ProjectID = "{9AC218D3-4571-402E-9408-D679EC504540}"
	End Property

	' Table Name
	Public Property Get TableName()
		TableName = "xwlm"
	End Property

	' Page Object Name
	Public Property Get PageObjName()
		PageObjName = "xwlm_grid"
	End Property

	' Grid form hidden field names
	Dim FormName
	Dim FormActionName
	Dim FormKeyName
	Dim FormOldKeyName
	Dim FormBlankRowName
	Dim FormKeyCountName

	' Page Name
	Public Property Get PageName()
		PageName = ew_CurrentPage()
	End Property

	' Page Url
	Public Property Get PageUrl()
		PageUrl = ew_CurrentPage() & "?"
		If xwlm.UseTokenInUrl Then PageUrl = PageUrl & "t=" & xwlm.TableVar & "&" ' add page token
	End Property

	' Message
	Public Property Get Message()
		Message = Session(EW_SESSION_MESSAGE)
	End Property

	Public Property Let Message(v)
		Dim msg
		msg = Session(EW_SESSION_MESSAGE)
		Call ew_AddMessage(msg, v)
		Session(EW_SESSION_MESSAGE) = msg
	End Property

	Public Property Get FailureMessage()
		FailureMessage = Session(EW_SESSION_FAILURE_MESSAGE)
	End Property

	Public Property Let FailureMessage(v)
		Dim msg
		msg = Session(EW_SESSION_FAILURE_MESSAGE)
		Call ew_AddMessage(msg, v)
		Session(EW_SESSION_FAILURE_MESSAGE) = msg
	End Property

	Public Property Get SuccessMessage()
		SuccessMessage = Session(EW_SESSION_SUCCESS_MESSAGE)
	End Property

	Public Property Let SuccessMessage(v)
		Dim msg
		msg = Session(EW_SESSION_SUCCESS_MESSAGE)
		Call ew_AddMessage(msg, v)
		Session(EW_SESSION_SUCCESS_MESSAGE) = msg
	End Property

	Public Property Get WarningMessage()
		WarningMessage = Session(EW_SESSION_WARNING_MESSAGE)
	End Property

	Public Property Let WarningMessage(v)
		Dim msg
		msg = Session(EW_SESSION_WARNING_MESSAGE)
		Call ew_AddMessage(msg, v)
		Session(EW_SESSION_WARNING_MESSAGE) = msg
	End Property

	' Show Message
	Public Sub ShowMessage()
		Dim hidden, html, sMessage
		hidden = False
		html = ""

		' Message
		sMessage = Message
		Call Message_Showing(sMessage, "")
		If sMessage <> "" Then ' Message in Session, display
			If Not hidden Then sMessage = "<button type=""button"" class=""close"" data-dismiss=""alert"">&times;</button>" & sMessage
			html = html & "<div class=""alert alert-success ewSuccess"">" & sMessage & "</div>"
			Session(EW_SESSION_MESSAGE) = "" ' Clear message in Session
		End If

		' Warning message
		Dim sWarningMessage
		sWarningMessage = WarningMessage
		Call Message_Showing(sWarningMessage, "warning")
		If sWarningMessage <> "" Then ' Message in Session, display
			If Not hidden Then sWarningMessage = "<button type=""button"" class=""close"" data-dismiss=""alert"">&times;</button>" & sWarningMessage
			html = html & "<div class=""alert alert-warning ewWarning"">" & sWarningMessage & "</div>"
			Session(EW_SESSION_WARNING_MESSAGE) = "" ' Clear message in Session
		End If

		' Success message
		Dim sSuccessMessage
		sSuccessMessage = SuccessMessage
		Call Message_Showing(sSuccessMessage, "success")
		If sSuccessMessage <> "" Then ' Message in Session, display
			If Not hidden Then sSuccessMessage = "<button type=""button"" class=""close"" data-dismiss=""alert"">&times;</button>" & sSuccessMessage
			html = html & "<div class=""alert alert-success ewSuccess"">" & sSuccessMessage & "</div>"
			Session(EW_SESSION_SUCCESS_MESSAGE) = "" ' Clear message in Session
		End If

		' Failure message
		Dim sErrorMessage
		sErrorMessage = FailureMessage
		Call Message_Showing(sErrorMessage, "failure")
		If sErrorMessage <> "" Then ' Message in Session, display
			If Not hidden Then sErrorMessage = "<button type=""button"" class=""close"" data-dismiss=""alert"">&times;</button>" & sErrorMessage
			html = html & "<div class=""alert alert-error ewError"">" & sErrorMessage & "</div>"
			Session(EW_SESSION_FAILURE_MESSAGE) = "" ' Clear message in Session
		End If
		Response.Write "<table class=""ewStdTable""><tr><td><div class=""ewMessageDialog""" & ew_IIf(hidden, " style=""display: none;""", "") & ">" & html & "</div></td></tr></table>"
	End Sub
	Dim PageHeader
	Dim PageFooter

	' Show Page Header
	Public Sub ShowPageHeader()
		Dim sHeader
		sHeader = PageHeader
		Call Page_DataRendering(sHeader)
		If sHeader <> "" Then ' Header exists, display
			Response.Write "<p>" & sHeader & "</p>"
		End If
	End Sub

	' Show Page Footer
	Public Sub ShowPageFooter()
		Dim sFooter
		sFooter = PageFooter
		Call Page_DataRendered(sFooter)
		If sFooter <> "" Then ' Footer exists, display
			Response.Write "<p>" & sFooter & "</p>"
		End If
	End Sub

	' -----------------------
	'  Validate Page request
	'
	Public Function IsPageRequest()
		If xwlm.UseTokenInUrl Then
			IsPageRequest = False
			If Not (ObjForm Is Nothing) Then
				IsPageRequest = (xwlm.TableVar = ObjForm.GetValue("t"))
			End If
			If Request.QueryString("t").Count > 0 Then
				IsPageRequest = (xwlm.TableVar = Request.QueryString("t"))
			End If
		Else
			IsPageRequest = True
		End If
	End Function

	' -----------------------------------------------------------------
	'  Class initialize
	'  - init objects
	'  - open ADO connection
	'
	Private Sub Class_Initialize()
		If IsEmpty(StartTimer) Then StartTimer = Timer ' Init start time

		' Grid form hidden field names
		FormName = "fxwlmgrid"
		FormActionName = "k_action" & "_" & FormName
		FormKeyName = "k_key" & "_" & FormName
		FormOldKeyName = "k_oldkey" & "_" & FormName
		FormBlankRowName = "k_blankrow" & "_" & FormName
		FormKeyCountName = "key_count" & "_" & FormName

		' Initialize language object
		If IsEmpty(Language) Then
			Set Language = New cLanguage
			Call Language.LoadPhrases()
		End If

		' Initialize table object
		If IsEmpty(xwlm) Then Set xwlm = New cxwlm
		Set Table = xwlm

		' Initialize urls
		' Initialize other table object

		If IsEmpty(zlogin) Then Set zlogin = New czlogin

		' Intialize page id (for backward compatibility)
		EW_PAGE_ID = "grid"

		' Initialize table name (for backward compatibility)
		EW_TABLE_NAME = "xwlm"

		' Open connection to the database
		If IsEmpty(Conn) Then Call ew_Connect()

		' List options
		Set ListOptions = New cListOptions
		ListOptions.TableVar = xwlm.TableVar

		' Other options
		Set AddEditOptions = New cListOptions
		AddEditOptions.Tag = "div"
		AddEditOptions.TagClassName = "ewAddEditOption"
	End Sub

	' -----------------------------------------------------------------
	'  Subroutine Page_Init
	'  - called before page main
	'  - check Security
	'  - set up response header
	'  - call page load events
	'
	Sub Page_Init()
		Set Security = New cAdvancedSecurity
		If Not Security.IsLoggedIn() Then Call Security.AutoLogin()
		If Not Security.IsLoggedIn() Then
			Call Security.SaveLastUrl()
			Call Page_Terminate("login.asp")
		End If

		' Table Permission loading event
		Call Security.TablePermission_Loading()
		Call Security.LoadCurrentUserLevel(ProjectID & TableName)

		' Table Permission loaded event
		Call Security.TablePermission_Loaded()
		If Not Security.IsLoggedIn() Then
			Call Security.SaveLastUrl()
			Call Page_Terminate("login.asp")
		End If
		If Not Security.CanList Then
			Call Security.SaveLastUrl()
			Call Page_Terminate("login.asp")
		End If

		' Get grid add count
		Dim gridaddcnt
		gridaddcnt = Request.QueryString(EW_TABLE_GRID_ADD_ROW_COUNT)
		If IsNumeric(gridaddcnt) Then
			If gridaddcnt > 0 Then
				xwlm.GridAddRowCount = gridaddcnt
			End If
		End If

		' Set up list options
		SetupListOptions()
		xwlm.lmid.Visible = Not xwlm.IsAdd() And Not xwlm.IsCopy() And Not xwlm.IsGridAdd()

		' Global page loading event (in userfn7.asp)
		Page_Loading()

		' Page load event, used in current page
		Page_Load()

		' Setup other options
		SetupOtherOptions()
	End Sub

	' -----------------------------------------------------------------
	'  Class terminate
	'  - clean up page object
	'
	Private Sub Class_Terminate()
		Call Page_Terminate("")
	End Sub

	' -----------------------------------------------------------------
	'  Subroutine Page_Terminate
	'  - called when exit page
	'  - clean up ADO connection and objects
	'  - if url specified, redirect to url
	'
	Sub Page_Terminate(url)
		Set Grid = Nothing
		If url = "" Then
			Exit Sub
		End If

		' Global page unloaded event (in userfn60.asp)
		Call Page_Unloaded()
		Dim sRedirectUrl
		sReDirectUrl = url
		Call Page_Redirecting(sReDirectUrl)
		Set Security = Nothing
		Set xwlm = Nothing

		' Go to url if specified
		If sReDirectUrl <> "" Then
			If Response.Buffer Then Response.Clear
			Response.Redirect sReDirectUrl
		End If
	End Sub

	'
	'  Subroutine Page_Terminate (End)
	' ----------------------------------------

	Dim ListOptions ' List options
	Dim ExportOptions ' Export options
	Dim AddEditOptions ' Other options (add edit)
	Dim DetailOptions ' Other options (detail)
	Dim ActionOptions ' Other options (action)
	Dim ShowOtherOptions
	Dim DisplayRecs ' Number of display records
	Dim StartRec, StopRec, TotalRecs, RecRange
	Dim SearchWhere
	Dim RecCnt
	Dim EditRowCnt
	Dim StartRowCnt
	Dim RowCnt, RowIndex
	Dim Attrs
	Dim RecPerRow, ColCnt
	Dim KeyCount
	Dim RowAction
	Dim RowOldKey ' Row old key (for copy)
	Dim DbMasterFilter, DbDetailFilter
	Dim MasterRecordExists
	Dim MultiSelectKey
	Dim Command
	Dim RestoreSearch
	Dim xwfb_Count
	Dim sjlm_Count
	Dim Recordset, OldRecordset

	' -----------------------------------------------------------------
	' Page main processing
	'
	Sub Page_Main()
		DisplayRecs = 20
		RecRange = 10
		RecCnt = 0 ' Record count
		KeyCount = 0 ' Key count
		StartRowCnt = 1

		' Search filters
		Dim sSrchAdvanced, sSrchBasic, sFilter
		sSrchAdvanced = "" ' Advanced search filter
		sSrchBasic = "" ' Basic search filter
		SearchWhere = "" ' Search where clause
		sFilter = ""

		' Restore search
		RestoreSearch = False

		' Get command
		Command = LCase(Request.QueryString("cmd")&"")

		' Master/Detail
		DbMasterFilter = "" ' Master filter
		DbDetailFilter = "" ' Detail filter
		If IsPageRequest Then ' Validate request

			' Set up records per page dynamically
			SetUpDisplayRecs()

			' Handle reset command
			ResetCmd()

			' Set up master detail parameters
			SetUpMasterParms()

			' Hide list options
			If xwlm.Export <> "" Then
				Call ListOptions.HideAllOptions(Array("sequence"))
				ListOptions.UseDropDownButton = False ' Disable drop down button
				ListOptions.UseButtonGroup = False ' Disable button group
			ElseIf xwlm.CurrentAction = "gridadd" Or xwlm.CurrentAction = "gridedit" Then
				Call ListOptions.HideAllOptions(Array())
				ListOptions.UseDropDownButton = False ' Disable drop down button
				ListOptions.UseButtonGroup = False ' Disable button group
			End If

			' Show grid delete link for grid add / grid edit
			If xwlm.AllowAddDeleteRow Then
				If xwlm.CurrentAction = "gridadd" Or xwlm.CurrentAction = "gridedit" Then
					ListOptions.GetItem("griddelete").Visible = True
				End If
			End If

			' Set Up Sorting Order
			SetUpSortOrder()
		End If ' End Validate Request

		' Restore display records
		If xwlm.RecordsPerPage <> "" Then
			DisplayRecs = xwlm.RecordsPerPage ' Restore from Session
		Else
			DisplayRecs = 20 ' Load default
		End If

		' Load Sorting Order
		LoadSortOrder()
		sFilter = ""
		If Not Security.CanList Then
			sFilter = "(0=1)" ' Filter all records
		End If

		' Restore master/detail filter
		DbMasterFilter = xwlm.MasterFilter ' Restore master filter
		DbDetailFilter = xwlm.DetailFilter ' Restore detail filter
		Call ew_AddFilter(sFilter, DbDetailFilter)
		Call ew_AddFilter(sFilter, SearchWhere)
		Dim RsMaster

		' Load master record
		If xwlm.MasterFilter <> "" And xwlm.CurrentMasterTable = "bhlm" Then
			Set RsMaster = bhlm.LoadRs(DbMasterFilter)
			MasterRecordExists = Not (RsMaster Is Nothing)
			If Not MasterRecordExists Then
			Else
				Call bhlm.LoadListRowValues(RsMaster)
				bhlm.RowType = EW_ROWTYPE_MASTER ' Master row
				Call bhlm.RenderListRow()
				RsMaster.Close
				Set RsMaster = Nothing
			End If
		End If

		' Set up filter in Session
		xwlm.SessionWhere = sFilter
		xwlm.CurrentFilter = ""
	End Sub

	' -----------------------------------------------------------------
	' Set up number of records displayed per page
	'
	Sub SetUpDisplayRecs()
		Dim sWrk
		sWrk = Request.QueryString(EW_TABLE_REC_PER_PAGE)
		If sWrk <> "" Then
			If IsNumeric(sWrk) Then
				DisplayRecs = CInt(sWrk)
			Else
				If LCase(sWrk) = "all" Then ' Display all records
					DisplayRecs = -1
				Else
					DisplayRecs = 20 ' Non-numeric, load default
				End If
			End If
			xwlm.RecordsPerPage = DisplayRecs ' Save to Session

			' Reset start position
			StartRec = 1
			xwlm.StartRecordNumber = StartRec
		End If
	End Sub

	' -----------------------------------------------------------------
	'  Exit out of inline mode
	'
	Sub ClearInlineMode()
		xwlm.LastAction = xwlm.CurrentAction ' Save last action
		xwlm.CurrentAction = "" ' Clear action
		Session(EW_SESSION_INLINE_MODE) = "" ' Clear inline mode
	End Sub

	' -----------------------------------------------------------------
	' Switch to Grid Add Mode
	'
	Sub GridAddMode()
		Session(EW_SESSION_INLINE_MODE) = "gridadd" ' Enabled grid add
	End Sub

	' -----------------------------------------------------------------
	' Switch to Grid Edit Mode
	'
	Sub GridEditMode()
		Session(EW_SESSION_INLINE_MODE) = "gridedit" ' Enabled grid edit
	End Sub

	' -----------------------------------------------------------------
	' Peform update to grid
	'
	Function GridUpdate()
		Dim rowindex
		Dim bGridUpdate
		Dim sKey, sThisKey
		Dim Rs, RsOld, RsNew, sSql
		rowindex = 1
		bGridUpdate = True

		' Get old recordset
		xwlm.CurrentFilter  = BuildKeyFilter()
		sSql = xwlm.SQL
		Set Rs = Server.CreateObject("ADODB.Recordset")
		Rs.CursorLocation = EW_CURSORLOCATION
		Rs.Open sSql, Conn, 1, EW_RECORDSET_LOCKTYPE
		Set RsOld = ew_CloneRs(Rs)
		sKey = ""

		' Update row index and get row key
		Dim rowcnt
		ObjForm.Index = -1
		rowcnt = ObjForm.GetValue(FormKeyCountName)
		If rowcnt = "" Or Not IsNumeric(rowcnt) Then
			rowcnt = 0
		End If

		' Update all rows based on key
		Dim rowkey, rowaction
		For rowindex = 1 to rowcnt
			ObjForm.Index = rowindex
			rowkey = ObjForm.GetValue(FormKeyName) & ""
			rowaction = ObjForm.GetValue(FormActionName) & ""

			' Load all values & keys
			If rowaction <> "insertdelete" Then ' Skip insert then deleted rows
				Call LoadFormValues() ' Get form values
				If rowaction = "" Or rowaction = "edit" Or rowaction = "delete" Then
					bGridUpdate = SetupKeyValues(rowkey) ' Set up key values
				Else
					bGridUpdate = True
				End If

				' Skip empty row
				If rowaction = "insert" And EmptyRow() Then

					' No action required
				' Validate form and insert/update/delete record

				ElseIf bGridUpdate Then
					If rowaction = "delete" Then
						xwlm.CurrentFilter = xwlm.KeyFilter
						bGridUpdate = DeleteRows() ' Delete this row
					ElseIf Not ValidateForm() Then
						bGridUpdate = False ' Form error, reset action
						FailureMessage = gsFormError
					Else
						If rowaction = "insert" Then
							bGridUpdate = AddRow(Null) ' Insert this row
						Else
							If rowkey <> "" Then
								xwlm.SendEmail = False ' Do not send email on update success

								' Set detail key fields disabled flag to skip update
								If xwlm.CurrentMasterTable = "bhlm" Then
									xwlm.bh.Disabled = True ' Set field disabled flag to skip update
								End If
								bGridUpdate = EditRow() ' Update this row

								' Reset detail key fields disabled flag
								If xwlm.CurrentMasterTable = "bhlm" Then
									xwlm.bh.Disabled = False ' Reset field disabled flag
								End If
							End If
						End If ' End update
					End If
				End If
				If bGridUpdate Then
					If sKey <> "" Then sKey = sKey & ", "
					sKey = sKey & rowkey
				Else
					Exit For
				End If
			End If
		Next
		If bGridUpdate Then

			' Get new recordset
			Set Rs = Conn.Execute(sSql)
			Set RsNew = ew_CloneRs(Rs)
			Call ClearInlineMode() ' Clear inline edit mode
		Else
			If FailureMessage = "" Then
				FailureMessage = Language.Phrase("UpdateFailed") ' Set update failed message
			End If
			xwlm.EventCancelled = True ' Set event cancelled
			xwlm.CurrentAction = "gridedit" ' Stay in gridedit mode
		End If
		Set Rs = Nothing
		Set RsOld = Nothing
		Set RsNew = Nothing
		GridUpdate = bGridUpdate
	End Function

	' -----------------------------------------------------------------
	'  Build filter for all keys
	'
	Function BuildKeyFilter()
		Dim rowindex, sThisKey
		Dim sKey
		Dim sWrkFilter, sFilter
		sWrkFilter = ""

		' Update row index and get row key
		rowindex = 1
		ObjForm.Index = rowindex
		sThisKey = ObjForm.GetValue("k_key") & ""
		Do While (sThisKey <> "")
			If SetupKeyValues(sThisKey) Then
				sFilter = xwlm.KeyFilter
				If sWrkFilter <> "" Then sWrkFilter = sWrkFilter & " OR "
				sWrkFilter = sWrkFilter & sFilter
			Else
				sWrkFilter = "0=1"
				Exit Do
			End If

			' Update row index and get row key
			rowindex = rowindex + 1 ' Next row
			ObjForm.Index = rowindex
			sThisKey = ObjForm.GetValue("k_key") & ""
		Loop
		BuildKeyFilter = sWrkFilter
	End Function

	' -----------------------------------------------------------------
	' Set up key values
	'
	Function SetupKeyValues(key)
		Dim arrKeyFlds
		arrKeyFlds = Split(key&"", EW_COMPOSITE_KEY_SEPARATOR)
		If UBound(arrKeyFlds) >= 0 Then
			xwlm.lmid.FormValue = arrKeyFlds(0)
			If Not IsNumeric(xwlm.lmid.FormValue) Then
				SetupKeyValues = False
				Exit Function
			End If
		End If
		SetupKeyValues = True
	End Function

	' Grid Insert
	' Peform insert to grid
	Function GridInsert()
		Dim addcnt
		Dim rowindex, rowcnt
		Dim bGridInsert
		Dim sSql, sWrkFilter, sFilter, sKey, sThisKey
		Dim Rs, RsNew
		rowindex = 1
		bGridInsert = False

		' Init key filter
		sWrkFilter = ""
		addcnt = 0
		sKey = ""

		' Get row count
		ObjForm.Index = -1
		rowcnt = ObjForm.GetValue(FormKeyCountName) & ""
		If rowcnt = "" Or Not IsNumeric(rowcnt) Then rowcnt = 0

		' Insert all rows
		For rowindex = 1 to rowcnt

			' Load current row values
			ObjForm.Index = rowindex
			Dim rowaction
			rowaction = ObjForm.GetValue(FormActionName) & ""
			If rowaction = "" Or rowaction = "insert" Then
				If rowaction = "insert" Then
					RowOldKey = ObjForm.GetValue(FormOldKeyName) & ""
					LoadOldRecord() ' Load old recordset
				End If
				Call LoadFormValues() ' Get form values
				If Not EmptyRow() Then
					addcnt = addcnt + 1
					xwlm.SendEmail = False ' Do not send email on insert success

					' Validate Form
					If Not ValidateForm() Then
						bGridInsert = False ' Form error, reset action
						FailureMessage = gsFormError
					Else
						bGridInsert = AddRow(Null) ' Insert this row
					End If
					If bGridInsert Then
						If sKey <> "" Then sKey = sKey & EW_COMPOSITE_KEY_SEPARATOR
						sKey = sKey & xwlm.lmid.CurrentValue

						' Add filter for this record
						sFilter = xwlm.KeyFilter
						If sWrkFilter <> "" Then sWrkFilter = sWrkFilter & " OR "
						sWrkFilter = sWrkFilter & sFilter
					Else
						Exit For
					End If
				End If
			End If
		Next
		If addcnt = 0 Then ' No record inserted
			Call ClearInlineMode() ' Clear grid add mode and return
			GridInsert = True
			Exit Function
		End If
		If bGridInsert Then

			' Get new recordset
			xwlm.CurrentFilter  = sWrkFilter
			sSql = xwlm.SQL
			Set Rs = Conn.Execute(sSql)
			Set RsNew = ew_CloneRs(Rs)
			Call ClearInlineMode() ' Clear grid add mode
		Else
			If FailureMessage = "" Then
				FailureMessage = Language.Phrase("InsertFailed") ' Set insert failed message
			End If
			xwlm.EventCancelled = True ' Set event cancelled
			xwlm.CurrentAction = "gridadd" ' Stay in gridadd mode
		End If
		Set Rs = Nothing
		Set RsNew = Nothing
		GridInsert = bGridInsert
	End Function

	' Check if empty row
	Function EmptyRow()
		EmptyRow = True
		If Not ObjForm Is Nothing Then
			If EmptyRow And ObjForm.HasValue("x_bh") And ObjForm.HasValue("o_bh") Then EmptyRow = (xwlm.bh.CurrentValue&"" = xwlm.bh.OldValue&"")
			If EmptyRow And ObjForm.HasValue("x_lmmc") And ObjForm.HasValue("o_lmmc") Then EmptyRow = (xwlm.lmmc.CurrentValue&"" = xwlm.lmmc.OldValue&"")
			If EmptyRow And ObjForm.HasValue("x_lmmc2") And ObjForm.HasValue("o_lmmc2") Then EmptyRow = (xwlm.lmmc2.CurrentValue&"" = xwlm.lmmc2.OldValue&"")
			If EmptyRow And ObjForm.HasValue("x_px") And ObjForm.HasValue("o_px") Then EmptyRow = (xwlm.px.CurrentValue&"" = xwlm.px.OldValue&"")
			If EmptyRow And ObjForm.HasValue("x_urllb") And ObjForm.HasValue("o_urllb") Then EmptyRow = (xwlm.urllb.CurrentValue&"" = xwlm.urllb.OldValue&"")
		End If
	End Function

	' Validate grid form
	Function ValidateGridForm()
		Dim rowindex, rowcnt, rowaction

		' Get row count
		ObjForm.Index = -1
		rowcnt = ObjForm.GetValue(FormKeyCountName) & ""
		If rowcnt = "" Or Not IsNumeric(rowcnt) Then
			rowcnt = 0
		End If

		' Validate all records
		ValidateGridForm = True
		For rowindex = 1 to rowcnt

			' Load current row values
			ObjForm.Index = rowindex
			rowaction = ObjForm.GetValue(FormActionName) & ""
			If rowaction <> "delete" And rowaction <> "insertdelete" Then
				LoadFormValues() ' Get form values
				If rowaction = "insert" And EmptyRow() Then

					' Ignore
				ElseIf Not ValidateForm() Then
					ValidateGridForm = False
					Exit For
				End If
			End If
		Next
	End Function

	' Restore form values for current row
	Sub RestoreCurrentRowFormValues(idx)

		' Get row based on current index
		ObjForm.Index = idx
		Call LoadFormValues() ' Load form values
	End Sub

	' -----------------------------------------------------------------
	' Set up Sort parameters based on Sort Links clicked
	'
	Sub SetUpSortOrder()
		Dim sOrderBy
		Dim sSortField, sLastSort, sThisSort
		Dim bCtrl

		' Check for an Order parameter
		If Request.QueryString("order").Count > 0 Then
			xwlm.CurrentOrder = Request.QueryString("order")
			xwlm.CurrentOrderType = Request.QueryString("ordertype")
			xwlm.StartRecordNumber = 1 ' Reset start position
		End If
	End Sub

	' -----------------------------------------------------------------
	' Load Sort Order parameters
	'
	Sub LoadSortOrder()
		Dim sOrderBy
		sOrderBy = xwlm.SessionOrderBy ' Get order by from Session
		If sOrderBy = "" Then
			If xwlm.SqlOrderBy <> "" Then
				sOrderBy = xwlm.SqlOrderBy
				xwlm.SessionOrderBy = sOrderBy
			End If
		End If
	End Sub

	' -----------------------------------------------------------------
	' Reset command based on querystring parameter cmd=
	' - RESET: reset search parameters
	' - RESETALL: reset search & master/detail parameters
	' - RESETSORT: reset sort parameters
	'
	Sub ResetCmd()

		' Check if reset command
		If Left(Command,5) = "reset" Then

			' Reset master/detail keys
			If Command = "resetall" Then
				xwlm.CurrentMasterTable = "" ' Clear master table
				DbMasterFilter = ""
				DbDetailFilter = ""
				xwlm.bh.SessionValue = ""
			End If

			' Reset Sort Criteria
			If Command = "resetsort" Then
				Dim sOrderBy
				sOrderBy = ""
				xwlm.SessionOrderBy = sOrderBy
			End If

			' Reset start position
			StartRec = 1
			xwlm.StartRecordNumber = StartRec
		End If
	End Sub

	' Set up list options
	Sub SetupListOptions()
		Dim item

		' Grid delete
		If xwlm.AllowAddDeleteRow Then
			ListOptions.Add("griddelete")
			Set item = ListOptions.GetItem("griddelete")
			item.CssStyle = "white-space: nowrap;"
			item.OnLeft = False
			item.Visible = False ' Default hidden
		End If

		' Add group option item
		ListOptions.Add(ListOptions.GroupOptionName)
		Set item = ListOptions.GetItem(ListOptions.GroupOptionName)
		item.Body = ""
		item.OnLeft = False
		item.Visible = False

		' Drop down button for ListOptions
		ListOptions.UseDropDownButton = False
		ListOptions.DropDownButtonPhrase = Language.Phrase("ButtonListOptions")
		ListOptions.UseButtonGroup = False
		ListOptions.ButtonClass = "btn-small" ' Class for button group

		' Set up group item visibility
		ListOptions.GetItem(ListOptions.GroupOptionName).Visible = ListOptions.GroupOptionVisible
	End Sub

	' Render list options
	Sub RenderListOptions()
		Dim item, links
		ListOptions.LoadDefault()

		' Set up row action and key
		If IsNumeric(RowIndex) And xwlm.CurrentMode <> "view" Then
			Dim ActionName, OldKeyName, KeyName, BlankRowName
			ObjForm.Index = RowIndex
			ActionName = Replace(FormActionName, "k_", "k" & RowIndex & "_")
			OldKeyName = Replace(FormOldKeyName, "k_", "k" & RowIndex & "_")
			KeyName = Replace(FormKeyName, "k_", "k" & RowIndex & "_")
			BlankRowName = Replace(FormBlankRowName, "k_", "k" & RowIndex & "_")
			If RowAction <> "" Then
				MultiSelectKey = MultiSelectKey & "<input type=""hidden"" name=""" & ActionName & """ id=""" & ActionName & """ value=""" & RowAction & """>"
			End If
			If ObjForm.HasValue(FormOldKeyName) Then
				RowOldKey = ObjForm.GetValue(FormOldKeyName) & ""
			End If
			If RowOldKey <> "" Then
				MultiSelectKey = MultiSelectKey & "<input type=""hidden"" name=""" & OldKeyName & """ id=""" & OldKeyName & """ value = """ & ew_HtmlEncode(RowOldKey) & """>"
			End If
			If RowAction = "delete" Then
				Dim sKey
				sKey = ObjForm.GetValue(FormKeyName) & ""
				Call SetupKeyValues(sKey)
			End If
			If RowAction = "insert" And xwlm.CurrentAction = "F" And EmptyRow() Then
				MultiSelectKey = MultiSelectKey & "<input type=""hidden"" name=""" & BlankRowName & """ id=""" & BlankRowName & """ value=""1"">"
			End If
		End If

		' Grid delete
		If xwlm.AllowAddDeleteRow Then
			If xwlm.CurrentMode = "add" Or xwlm.CurrentMode = "copy" Or xwlm.CurrentMode = "edit" Then
				ListOptions.UseButtonGroup = True ' Use button group for grid delete button
				ListOptions.UseImageAndText = True ' Use image and text for grid delete button
				Set item = ListOptions.GetItem("griddelete")
				If Not Security.CanDelete() And IsNumeric(RowIndex) And (RowAction = "" Or RowAction = "edit") Then ' Do not allow delete existing record
					item.Body = "&nbsp;"
				Else
					item.Body = "<a class=""ewGridLink ewGridDelete"" data-caption=""" & ew_HtmlTitle(Language.Phrase("DeleteLink")) & """ href=""javascript:void(0);"" onclick=""ew_DeleteGridRow(this, " & RowIndex & ");"">" & Language.Phrase("DeleteLink") & "</a>"
				End If
			End If
		End If
		If xwlm.CurrentMode = "edit" And RowIndex <> "" And IsNumeric(RowIndex) Then
			MultiSelectKey = MultiSelectKey & "<input type=""hidden"" name=""" & KeyName & """ id=""" & KeyName & """ value=""" & xwlm.lmid.CurrentValue & """>"
		End If
		Call RenderListOptionsExt()
	End Sub

	' Set record key
	Function SetRecordKey(rs)
		Dim key
		key = ""
		SetRecordKey = key
		If rs.Eof Then Exit Function
		If (key <> "") Then key = key & EW_COMPOSITE_KEY_SEPARATOR
		key = key & rs("lmid")
		SetRecordKey = key
	End Function

	' Set up other options
	Sub SetupOtherOptions()
		Dim opt, item, DetailTableLink, ar, i
		Set opt = AddEditOptions
		opt.UseDropDownButton = False
		opt.DropDownButtonPhrase = Language.Phrase("ButtonAddEdit")
		opt.UseButtonGroup = True
		opt.ButtonClass = "btn-small" ' Class for button group
		Call opt.Add(opt.GroupOptionName)
		Set item = opt.GetItem(opt.GroupOptionName)
		item.Body = ""
		item.Visible = False
	End Sub

	' Render other options
	Sub RenderOtherOptions()
		Dim opt, item, i, Action, Name
		If (xwlm.CurrentMode = "add" Or xwlm.CurrentMode = "copy" Or xwlm.CurrentMode = "edit") And xwlm.CurrentAction <> "F" Then ' Check add/copy/edit mode
			If xwlm.AllowAddDeleteRow Then
				Set opt = AddEditOptions
				opt.UseDropDownButton = False
				opt.UseImageAndText = True
				Call opt.Add("addblankrow")
				Set item = opt.GetItem("addblankrow")
				item.Body = "<a class=""ewAddEdit ewAddBlankRow"" data-caption=""" & ew_HtmlTitle(Language.Phrase("AddBlankRow")) & """ href=""javascript:void(0);"" onclick=""ew_AddGridRow(this);"">" & Language.Phrase("AddBlankRow") & "</a>"
				item.Visible = Security.CanAdd
				ShowOtherOptions = item.Visible
			End If
		End If
	End Sub

	Function RenderListOptionsExt()
	End Function
	Dim Pager

	' -----------------------------------------------------------------
	' Set up Starting Record parameters based on Pager Navigation
	'
	Sub SetUpStartRec()
		Dim PageNo

		' Exit if DisplayRecs = 0
		If DisplayRecs = 0 Then Exit Sub
		If IsPageRequest Then ' Validate request

			' Check for a START parameter
			If Request.QueryString(EW_TABLE_START_REC).Count > 0 Then
				StartRec = Request.QueryString(EW_TABLE_START_REC)
				xwlm.StartRecordNumber = StartRec
			ElseIf Request.QueryString(EW_TABLE_PAGE_NO).Count > 0 Then
				PageNo = Request.QueryString(EW_TABLE_PAGE_NO)
				If IsNumeric(PageNo) Then
					StartRec = (PageNo-1)*DisplayRecs+1
					If StartRec <= 0 Then
						StartRec = 1
					ElseIf StartRec >= ((TotalRecs-1)\DisplayRecs)*DisplayRecs+1 Then
						StartRec = ((TotalRecs-1)\DisplayRecs)*DisplayRecs+1
					End If
					xwlm.StartRecordNumber = StartRec
				End If
			End If
		End If
		StartRec = xwlm.StartRecordNumber

		' Check if correct start record counter
		If Not IsNumeric(StartRec) Or StartRec = "" Then ' Avoid invalid start record counter
			StartRec = 1 ' Reset start record counter
			xwlm.StartRecordNumber = StartRec
		ElseIf CLng(StartRec) > CLng(TotalRecs) Then ' Avoid starting record > total records
			StartRec = ((TotalRecs-1)\DisplayRecs)*DisplayRecs+1 ' Point to last page first record
			xwlm.StartRecordNumber = StartRec
		ElseIf (StartRec-1) Mod DisplayRecs <> 0 Then
			StartRec = ((StartRec-1)\DisplayRecs)*DisplayRecs+1 ' Point to page boundary
			xwlm.StartRecordNumber = StartRec
		End If
	End Sub

	' -----------------------------------------------------------------
	' Function Get upload files
	'
	Function GetUploadFiles()

		' Get upload data
	End Function

	' -----------------------------------------------------------------
	' Load default values
	'
	Function LoadDefaultValues()
		xwlm.lmid.CurrentValue = Null
		xwlm.lmid.OldValue = xwlm.lmid.CurrentValue
		xwlm.bh.CurrentValue = 0
		xwlm.bh.OldValue = xwlm.bh.CurrentValue
		xwlm.lmmc.CurrentValue = Null
		xwlm.lmmc.OldValue = xwlm.lmmc.CurrentValue
		xwlm.lmmc2.CurrentValue = Null
		xwlm.lmmc2.OldValue = xwlm.lmmc2.CurrentValue
		xwlm.px.CurrentValue = 0
		xwlm.px.OldValue = xwlm.px.CurrentValue
		xwlm.urllb.CurrentValue = 0
		xwlm.urllb.OldValue = xwlm.urllb.CurrentValue
	End Function

	' -----------------------------------------------------------------
	' Load form values
	'
	Function LoadFormValues()

		' Load values from form
		ObjForm.FormName = FormName
		If Not xwlm.lmid.FldIsDetailKey And xwlm.CurrentAction <> "gridadd" And xwlm.CurrentAction <> "add" Then xwlm.lmid.FormValue = ObjForm.GetValue("x_lmid")
		If Not xwlm.bh.FldIsDetailKey Then xwlm.bh.FormValue = ObjForm.GetValue("x_bh")
		xwlm.bh.OldValue = ObjForm.GetValue("o_bh")
		If Not xwlm.lmmc.FldIsDetailKey Then xwlm.lmmc.FormValue = ObjForm.GetValue("x_lmmc")
		xwlm.lmmc.OldValue = ObjForm.GetValue("o_lmmc")
		If Not xwlm.lmmc2.FldIsDetailKey Then xwlm.lmmc2.FormValue = ObjForm.GetValue("x_lmmc2")
		xwlm.lmmc2.OldValue = ObjForm.GetValue("o_lmmc2")
		If Not xwlm.px.FldIsDetailKey Then xwlm.px.FormValue = ObjForm.GetValue("x_px")
		xwlm.px.OldValue = ObjForm.GetValue("o_px")
		If Not xwlm.urllb.FldIsDetailKey Then xwlm.urllb.FormValue = ObjForm.GetValue("x_urllb")
		xwlm.urllb.OldValue = ObjForm.GetValue("o_urllb")
	End Function

	' -----------------------------------------------------------------
	' Restore form values
	'
	Function RestoreFormValues()
		If xwlm.CurrentAction <> "gridadd" And xwlm.CurrentAction <> "add" Then xwlm.lmid.CurrentValue = xwlm.lmid.FormValue
		xwlm.bh.CurrentValue = xwlm.bh.FormValue
		xwlm.lmmc.CurrentValue = xwlm.lmmc.FormValue
		xwlm.lmmc2.CurrentValue = xwlm.lmmc2.FormValue
		xwlm.px.CurrentValue = xwlm.px.FormValue
		xwlm.urllb.CurrentValue = xwlm.urllb.FormValue
	End Function

	' -----------------------------------------------------------------
	' Load recordset
	'
	Function LoadRecordset()

		' Call Recordset Selecting event
		Dim sFilter
		sFilter = xwlm.CurrentFilter
		Call xwlm.Recordset_Selecting(sFilter)
		xwlm.CurrentFilter = sFilter

		' Load list page sql
		Dim sSql
		sSql = xwlm.ListSQL
		Call ew_SetDebugMsg("LoadRecordset: " & sSql) ' Show SQL for debugging

		' Load recordset
		Dim RsRecordset
		Set RsRecordset = ew_LoadRecordset(sSql)

		' Call Recordset Selected event
		Call xwlm.Recordset_Selected(RsRecordset)
		Set LoadRecordset = RsRecordset
	End Function

	' -----------------------------------------------------------------
	' Load row based on key values
	'
	Function LoadRow()
		Dim RsRow, sSql, sFilter
		sFilter = xwlm.KeyFilter

		' Call Row Selecting event
		Call xwlm.Row_Selecting(sFilter)

		' Load sql based on filter
		xwlm.CurrentFilter = sFilter
		sSql = xwlm.SQL
		Call ew_SetDebugMsg("LoadRow: " & sSql) ' Show SQL for debugging
		Set RsRow = ew_LoadRow(sSql)
		If RsRow.Eof Then
			LoadRow = False
		Else
			LoadRow = True
			RsRow.MoveFirst
			Call LoadRowValues(RsRow) ' Load row values
		End If
		RsRow.Close
		Set RsRow = Nothing
	End Function

	' -----------------------------------------------------------------
	' Load row values from recordset
	'
	Sub LoadRowValues(RsRow)
		Dim sDetailFilter
		If Not EW_DEBUG_ENABLED Then On Error Resume Next
		If RsRow.Eof Then Exit Sub

		' Call Row Selected event
		Call xwlm.Row_Selected(RsRow)
		xwlm.lmid.DbValue = RsRow("lmid")
		xwlm.bh.DbValue = RsRow("bh")
		xwlm.lmmc.DbValue = RsRow("lmmc")
		xwlm.lmmc2.DbValue = RsRow("lmmc2")
		xwlm.px.DbValue = RsRow("px")
		xwlm.urllb.DbValue = RsRow("urllb")
		xwlm.js.DbValue = RsRow("js")
		xwlm.pic.DbValue = RsRow("pic")
	End Sub

	' Load DbValue from recordset
	Sub LoadDbValues(Rs)
		If Not EW_DEBUG_ENABLED Then On Error Resume Next
		If Rs.Eof Then Exit Sub
		xwlm.lmid.m_DbValue = Rs("lmid")
		xwlm.bh.m_DbValue = Rs("bh")
		xwlm.lmmc.m_DbValue = Rs("lmmc")
		xwlm.lmmc2.m_DbValue = Rs("lmmc2")
		xwlm.px.m_DbValue = Rs("px")
		xwlm.urllb.m_DbValue = Rs("urllb")
		xwlm.js.m_DbValue = Rs("js")
		xwlm.pic.m_DbValue = Rs("pic")
	End Sub

	' Load old record
	Function LoadOldRecord()

		' Load key values from Session
		Dim bValidKey
		bValidKey = True
		Dim arKeys, cnt
		ReDim arKeys(0)
		arKeys(0) = RowOldKey
		cnt = UBound(arKeys)+1
		If cnt >= 1 Then
			If arKeys(0) & "" <> "" Then
				xwlm.lmid.CurrentValue = arKeys(0) & "" ' lmid
			Else
				bValidKey = False
			End If
		Else
			bValidKey = False
		End If

		' Load old recordset
		If bValidKey Then
			xwlm.CurrentFilter = xwlm.KeyFilter
			Dim sSql
			sSql = xwlm.SQL
			Set OldRecordset = ew_LoadRecordset(sSql)
			Call LoadRowValues(OldRecordset) ' Load row values
		Else
			OldRecordset = Null
		End If
		LoadOldRecord = bValidKey
	End Function

	' -----------------------------------------------------------------
	' Render row values based on field settings
	'
	Sub RenderRow()

		' Initialize urls
		' Call Row Rendering event

		Call xwlm.Row_Rendering()

		' ---------------------------------------
		'  Common render codes for all row types
		' ---------------------------------------
		' lmid
		' bh
		' lmmc
		' lmmc2
		' px
		' urllb
		' js
		' pic
		' -----------
		'  View  Row
		' -----------

		If xwlm.RowType = EW_ROWTYPE_VIEW Then ' View row

			' lmid
			xwlm.lmid.ViewValue = xwlm.lmid.CurrentValue
			xwlm.lmid.ViewCustomAttributes = ""

			' bh
			If xwlm.bh.CurrentValue & "" <> "" Then
				sFilterWrk = "[bh]" & ew_SearchString("=", xwlm.bh.CurrentValue, EW_DATATYPE_NUMBER)
			sSqlWrk = "SELECT [bh], [bhmc] AS [DispFld], '' AS [Disp2Fld], '' AS [Disp3Fld], '' AS [Disp4Fld] FROM [bhlm]"
			sWhereWrk = ""
			Call ew_AddFilter(sWhereWrk, sFilterWrk)

			' Call Lookup selecting
			Call xwlm.Lookup_Selecting(xwlm.bh, sWhereWrk)
			If sWhereWrk <> "" Then sSqlWrk = sSqlWrk & " WHERE " & sWhereWrk
				Set RsWrk = Conn.Execute(sSqlWrk)
				If Not RsWrk.Eof Then
					xwlm.bh.ViewValue = RsWrk("DispFld")
				Else
					xwlm.bh.ViewValue = xwlm.bh.CurrentValue
				End If
				RsWrk.Close
				Set RsWrk = Nothing
			Else
				xwlm.bh.ViewValue = Null
			End If
			xwlm.bh.ViewCustomAttributes = ""

			' lmmc
			xwlm.lmmc.ViewValue = xwlm.lmmc.CurrentValue
			xwlm.lmmc.ViewCustomAttributes = ""

			' lmmc2
			xwlm.lmmc2.ViewValue = xwlm.lmmc2.CurrentValue
			xwlm.lmmc2.ViewCustomAttributes = ""

			' px
			xwlm.px.ViewValue = xwlm.px.CurrentValue
			xwlm.px.ViewCustomAttributes = ""

			' urllb
			If Not IsNull(xwlm.urllb.CurrentValue) Then
				Select Case xwlm.urllb.CurrentValue & ""
					Case xwlm.urllb.FldTagValue(1)
						xwlm.urllb.ViewValue = ew_IIf(xwlm.urllb.FldTagCaption(1) <> "", xwlm.urllb.FldTagCaption(1), xwlm.urllb.CurrentValue)
					Case xwlm.urllb.FldTagValue(2)
						xwlm.urllb.ViewValue = ew_IIf(xwlm.urllb.FldTagCaption(2) <> "", xwlm.urllb.FldTagCaption(2), xwlm.urllb.CurrentValue)
					Case xwlm.urllb.FldTagValue(3)
						xwlm.urllb.ViewValue = ew_IIf(xwlm.urllb.FldTagCaption(3) <> "", xwlm.urllb.FldTagCaption(3), xwlm.urllb.CurrentValue)
					Case Else
						xwlm.urllb.ViewValue = xwlm.urllb.CurrentValue
				End Select
			Else
				xwlm.urllb.ViewValue = Null
			End If
			xwlm.urllb.ViewCustomAttributes = ""

			' View refer script
			' lmid

			xwlm.lmid.LinkCustomAttributes = ""
			xwlm.lmid.HrefValue = ""
			xwlm.lmid.TooltipValue = ""

			' bh
			xwlm.bh.LinkCustomAttributes = ""
			xwlm.bh.HrefValue = ""
			xwlm.bh.TooltipValue = ""

			' lmmc
			xwlm.lmmc.LinkCustomAttributes = ""
			xwlm.lmmc.HrefValue = ""
			xwlm.lmmc.TooltipValue = ""

			' lmmc2
			xwlm.lmmc2.LinkCustomAttributes = ""
			xwlm.lmmc2.HrefValue = ""
			xwlm.lmmc2.TooltipValue = ""

			' px
			xwlm.px.LinkCustomAttributes = ""
			xwlm.px.HrefValue = ""
			xwlm.px.TooltipValue = ""

			' urllb
			xwlm.urllb.LinkCustomAttributes = ""
			xwlm.urllb.HrefValue = ""
			xwlm.urllb.TooltipValue = ""

		' ---------
		'  Add Row
		' ---------

		ElseIf xwlm.RowType = EW_ROWTYPE_ADD Then ' Add row

			' lmid
			' bh

			xwlm.bh.EditCustomAttributes = ""
			If xwlm.bh.SessionValue <> "" Then
				xwlm.bh.CurrentValue = xwlm.bh.SessionValue
				xwlm.bh.OldValue = xwlm.bh.CurrentValue
			If xwlm.bh.CurrentValue & "" <> "" Then
				sFilterWrk = "[bh]" & ew_SearchString("=", xwlm.bh.CurrentValue, EW_DATATYPE_NUMBER)
			sSqlWrk = "SELECT [bh], [bhmc] AS [DispFld], '' AS [Disp2Fld], '' AS [Disp3Fld], '' AS [Disp4Fld] FROM [bhlm]"
			sWhereWrk = ""
			Call ew_AddFilter(sWhereWrk, sFilterWrk)

			' Call Lookup selecting
			Call xwlm.Lookup_Selecting(xwlm.bh, sWhereWrk)
			If sWhereWrk <> "" Then sSqlWrk = sSqlWrk & " WHERE " & sWhereWrk
				Set RsWrk = Conn.Execute(sSqlWrk)
				If Not RsWrk.Eof Then
					xwlm.bh.ViewValue = RsWrk("DispFld")
				Else
					xwlm.bh.ViewValue = xwlm.bh.CurrentValue
				End If
				RsWrk.Close
				Set RsWrk = Nothing
			Else
				xwlm.bh.ViewValue = Null
			End If
			xwlm.bh.ViewCustomAttributes = ""
			Else
			sFilterWrk = ""
			sSqlWrk = "SELECT [bh], [bhmc] AS [DispFld], '' AS [Disp2Fld], '' AS [Disp3Fld], '' AS [Disp4Fld], '' AS [SelectFilterFld], '' AS [SelectFilterFld2], '' AS [SelectFilterFld3], '' AS [SelectFilterFld4] FROM [bhlm]"
			sWhereWrk = ""
			Call ew_AddFilter(sWhereWrk, sFilterWrk)

			' Call Lookup selecting
			Call xwlm.Lookup_Selecting(xwlm.bh, sWhereWrk)
			If sWhereWrk <> "" Then sSqlWrk = sSqlWrk & " WHERE " & sWhereWrk
			Set RsWrk = Server.CreateObject("ADODB.Recordset")
			RsWrk.Open sSqlWrk, Conn
			If Not RsWrk.Eof Then
				arwrk = RsWrk.GetRows
			Else
				arwrk = ""
			End If
			RsWrk.Close
			Set RsWrk = Nothing
			arwrk = ew_AddItemToArray(arwrk, 0, Array("", Language.Phrase("PleaseSelect"), "", "", "", "", "", "", ""))
			xwlm.bh.EditValue = arwrk
			End If

			' lmmc
			xwlm.lmmc.EditCustomAttributes = ""
			xwlm.lmmc.EditValue = ew_HtmlEncode(xwlm.lmmc.CurrentValue)
			xwlm.lmmc.PlaceHolder = ew_HtmlEncode(ew_RemoveHtml(xwlm.lmmc.FldCaption))

			' lmmc2
			xwlm.lmmc2.EditCustomAttributes = ""
			xwlm.lmmc2.EditValue = ew_HtmlEncode(xwlm.lmmc2.CurrentValue)
			xwlm.lmmc2.PlaceHolder = ew_HtmlEncode(ew_RemoveHtml(xwlm.lmmc2.FldCaption))

			' px
			xwlm.px.EditCustomAttributes = ""
			xwlm.px.EditValue = ew_HtmlEncode(xwlm.px.CurrentValue)
			xwlm.px.PlaceHolder = ew_HtmlEncode(ew_RemoveHtml(xwlm.px.FldCaption))

			' urllb
			xwlm.urllb.EditCustomAttributes = ""
			Redim arwrk(1, 2)
			arwrk(0, 0) = xwlm.urllb.FldTagValue(1)
			arwrk(1, 0) = ew_IIf(xwlm.urllb.FldTagCaption(1) <> "", xwlm.urllb.FldTagCaption(1), xwlm.urllb.FldTagValue(1))
			arwrk(0, 1) = xwlm.urllb.FldTagValue(2)
			arwrk(1, 1) = ew_IIf(xwlm.urllb.FldTagCaption(2) <> "", xwlm.urllb.FldTagCaption(2), xwlm.urllb.FldTagValue(2))
			arwrk(0, 2) = xwlm.urllb.FldTagValue(3)
			arwrk(1, 2) = ew_IIf(xwlm.urllb.FldTagCaption(3) <> "", xwlm.urllb.FldTagCaption(3), xwlm.urllb.FldTagValue(3))
			xwlm.urllb.EditValue = arwrk

			' Edit refer script
			' lmid

			xwlm.lmid.HrefValue = ""

			' bh
			xwlm.bh.HrefValue = ""

			' lmmc
			xwlm.lmmc.HrefValue = ""

			' lmmc2
			xwlm.lmmc2.HrefValue = ""

			' px
			xwlm.px.HrefValue = ""

			' urllb
			xwlm.urllb.HrefValue = ""

		' ----------
		'  Edit Row
		' ----------

		ElseIf xwlm.RowType = EW_ROWTYPE_EDIT Then ' Edit row

			' lmid
			xwlm.lmid.EditCustomAttributes = ""
			xwlm.lmid.EditValue = xwlm.lmid.CurrentValue
			xwlm.lmid.ViewCustomAttributes = ""

			' bh
			xwlm.bh.EditCustomAttributes = ""
			If xwlm.bh.SessionValue <> "" Then
				xwlm.bh.CurrentValue = xwlm.bh.SessionValue
				xwlm.bh.OldValue = xwlm.bh.CurrentValue
			If xwlm.bh.CurrentValue & "" <> "" Then
				sFilterWrk = "[bh]" & ew_SearchString("=", xwlm.bh.CurrentValue, EW_DATATYPE_NUMBER)
			sSqlWrk = "SELECT [bh], [bhmc] AS [DispFld], '' AS [Disp2Fld], '' AS [Disp3Fld], '' AS [Disp4Fld] FROM [bhlm]"
			sWhereWrk = ""
			Call ew_AddFilter(sWhereWrk, sFilterWrk)

			' Call Lookup selecting
			Call xwlm.Lookup_Selecting(xwlm.bh, sWhereWrk)
			If sWhereWrk <> "" Then sSqlWrk = sSqlWrk & " WHERE " & sWhereWrk
				Set RsWrk = Conn.Execute(sSqlWrk)
				If Not RsWrk.Eof Then
					xwlm.bh.ViewValue = RsWrk("DispFld")
				Else
					xwlm.bh.ViewValue = xwlm.bh.CurrentValue
				End If
				RsWrk.Close
				Set RsWrk = Nothing
			Else
				xwlm.bh.ViewValue = Null
			End If
			xwlm.bh.ViewCustomAttributes = ""
			Else
			sFilterWrk = ""
			sSqlWrk = "SELECT [bh], [bhmc] AS [DispFld], '' AS [Disp2Fld], '' AS [Disp3Fld], '' AS [Disp4Fld], '' AS [SelectFilterFld], '' AS [SelectFilterFld2], '' AS [SelectFilterFld3], '' AS [SelectFilterFld4] FROM [bhlm]"
			sWhereWrk = ""
			Call ew_AddFilter(sWhereWrk, sFilterWrk)

			' Call Lookup selecting
			Call xwlm.Lookup_Selecting(xwlm.bh, sWhereWrk)
			If sWhereWrk <> "" Then sSqlWrk = sSqlWrk & " WHERE " & sWhereWrk
			Set RsWrk = Server.CreateObject("ADODB.Recordset")
			RsWrk.Open sSqlWrk, Conn
			If Not RsWrk.Eof Then
				arwrk = RsWrk.GetRows
			Else
				arwrk = ""
			End If
			RsWrk.Close
			Set RsWrk = Nothing
			arwrk = ew_AddItemToArray(arwrk, 0, Array("", Language.Phrase("PleaseSelect"), "", "", "", "", "", "", ""))
			xwlm.bh.EditValue = arwrk
			End If

			' lmmc
			xwlm.lmmc.EditCustomAttributes = ""
			xwlm.lmmc.EditValue = ew_HtmlEncode(xwlm.lmmc.CurrentValue)
			xwlm.lmmc.PlaceHolder = ew_HtmlEncode(ew_RemoveHtml(xwlm.lmmc.FldCaption))

			' lmmc2
			xwlm.lmmc2.EditCustomAttributes = ""
			xwlm.lmmc2.EditValue = ew_HtmlEncode(xwlm.lmmc2.CurrentValue)
			xwlm.lmmc2.PlaceHolder = ew_HtmlEncode(ew_RemoveHtml(xwlm.lmmc2.FldCaption))

			' px
			xwlm.px.EditCustomAttributes = ""
			xwlm.px.EditValue = ew_HtmlEncode(xwlm.px.CurrentValue)
			xwlm.px.PlaceHolder = ew_HtmlEncode(ew_RemoveHtml(xwlm.px.FldCaption))

			' urllb
			xwlm.urllb.EditCustomAttributes = ""
			Redim arwrk(1, 2)
			arwrk(0, 0) = xwlm.urllb.FldTagValue(1)
			arwrk(1, 0) = ew_IIf(xwlm.urllb.FldTagCaption(1) <> "", xwlm.urllb.FldTagCaption(1), xwlm.urllb.FldTagValue(1))
			arwrk(0, 1) = xwlm.urllb.FldTagValue(2)
			arwrk(1, 1) = ew_IIf(xwlm.urllb.FldTagCaption(2) <> "", xwlm.urllb.FldTagCaption(2), xwlm.urllb.FldTagValue(2))
			arwrk(0, 2) = xwlm.urllb.FldTagValue(3)
			arwrk(1, 2) = ew_IIf(xwlm.urllb.FldTagCaption(3) <> "", xwlm.urllb.FldTagCaption(3), xwlm.urllb.FldTagValue(3))
			xwlm.urllb.EditValue = arwrk

			' Edit refer script
			' lmid

			xwlm.lmid.HrefValue = ""

			' bh
			xwlm.bh.HrefValue = ""

			' lmmc
			xwlm.lmmc.HrefValue = ""

			' lmmc2
			xwlm.lmmc2.HrefValue = ""

			' px
			xwlm.px.HrefValue = ""

			' urllb
			xwlm.urllb.HrefValue = ""
		End If
		If xwlm.RowType = EW_ROWTYPE_ADD Or xwlm.RowType = EW_ROWTYPE_EDIT Or xwlm.RowType = EW_ROWTYPE_SEARCH Then ' Add / Edit / Search row
			Call xwlm.SetupFieldTitles()
		End If

		' Call Row Rendered event
		If xwlm.RowType <> EW_ROWTYPE_AGGREGATEINIT Then
			Call xwlm.Row_Rendered()
		End If
	End Sub

	' -----------------------------------------------------------------
	' Validate form
	'
	Function ValidateForm()

		' Check if validation required
		If Not EW_SERVER_VALIDATE Then
			ValidateForm = (gsFormError = "")
			Exit Function
		End If
		If Not ew_CheckInteger(xwlm.px.FormValue) Then
			Call ew_AddMessage(gsFormError, xwlm.px.FldErrMsg)
		End If

		' Return validate result
		ValidateForm = (gsFormError = "")

		' Call Form Custom Validate event
		Dim sFormCustomError
		sFormCustomError = ""
		ValidateForm = ValidateForm And Form_CustomValidate(sFormCustomError)
		If sFormCustomError <> "" Then
			Call ew_AddMessage(gsFormError, sFormCustomError)
		End If
	End Function

	'
	' Delete records based on current filter
	'
	Function DeleteRows()
		If Not EW_DEBUG_ENABLED Then On Error Resume Next
		Dim sKey, sThisKey, sKeyFld, arKeyFlds
		Dim sSql, RsDelete
		Dim RsOld, RsDetail
		DeleteRows = True
		sSql = xwlm.SQL
		If Not Security.CanDelete Then
			FailureMessage = Language.Phrase("NoDeletePermission") ' No delete permission
			DeleteRows = False
			Exit Function
		End If
		Set RsDelete = Server.CreateObject("ADODB.Recordset")
		RsDelete.CursorLocation = EW_CURSORLOCATION
		RsDelete.Open sSql, Conn, 1, EW_RECORDSET_LOCKTYPE
		If Err.Number <> 0 Then
			FailureMessage = Err.Description
			RsDelete.Close
			Set RsDelete = Nothing
			DeleteRows = False
			Exit Function
		ElseIf RsDelete.Eof Then
			FailureMessage = Language.Phrase("NoRecord") ' No record found
			RsDelete.Close
			Set RsDelete = Nothing
			DeleteRows = False
			Exit Function
		End If

		' Clone old recordset object
		Set RsOld = ew_CloneRs(RsDelete)

		' Call row deleting event
		If DeleteRows Then
			RsDelete.MoveFirst
			Do While Not RsDelete.Eof
				DeleteRows = xwlm.Row_Deleting(RsDelete)
				If Not DeleteRows Then Exit Do
				RsDelete.MoveNext
			Loop
			RsDelete.MoveFirst
		End If
		If DeleteRows Then
			sKey = ""
			RsDelete.MoveFirst
			Do While Not RsDelete.Eof
				sThisKey = ""
				If sThisKey <> "" Then sThisKey = sThisKey & EW_COMPOSITE_KEY_SEPARATOR
				sThisKey = sThisKey & RsDelete("lmid")
				Call LoadDbValues(RsDelete)

				' Cascade delete detail records if necessary
				DeleteRows = xwlm.DeleteDetailRecords(RsDelete, "")
				If DeleteRows Then
					RsDelete.Delete
				End If
				If Err.Number <> 0 Or Not DeleteRows Then
					If Err.Description <> "" Then FailureMessage = Err.Description ' Set up error message
					DeleteRows = False
					Exit Do
				End If
				If sKey <> "" Then sKey = sKey & ", "
				sKey = sKey & sThisKey
				RsDelete.MoveNext
			Loop
		Else

			' Set up error message
			If SuccessMessage <> "" Or FailureMessage <> "" Then

				' Use the message, do nothing
			ElseIf xwlm.CancelMessage <> "" Then
				FailureMessage = xwlm.CancelMessage
				xwlm.CancelMessage = ""
			Else
				FailureMessage = Language.Phrase("DeleteCancelled")
			End If
		End If
		If DeleteRows Then
		Else
		End If
		RsDelete.Close
		Set RsDelete = Nothing

		' Call row deleting event
		If DeleteRows Then
			RsOld.MoveFirst
			Do While Not RsOld.Eof
				Call xwlm.Row_Deleted(RsOld)
				RsOld.MoveNext
			Loop
		End If
		RsOld.Close
		Set RsOld = Nothing
	End Function

	' -----------------------------------------------------------------
	' Update record based on key values
	'
	Function EditRow()
		If Not EW_DEBUG_ENABLED Then On Error Resume Next
		Dim Rs, sSql, sFilter
		Dim RsChk, sSqlChk, sFilterChk
		Dim bUpdateRow
		Dim RsOld, RsNew
		Dim sIdxErrMsg

		' Clear any previous errors
		Err.Clear
		sFilter = xwlm.KeyFilter
		xwlm.CurrentFilter  = sFilter
		sSql = xwlm.SQL
		Set Rs = Server.CreateObject("ADODB.Recordset")
		Rs.CursorLocation = EW_CURSORLOCATION
		Rs.Open sSql, Conn, 1, EW_RECORDSET_LOCKTYPE
		If Err.Number <> 0 Then
			Message = Err.Description
			Rs.Close
			Set Rs = Nothing
			EditRow = False
			Exit Function
		End If

		' Clone old recordset object
		Set RsOld = ew_CloneRs(Rs)
		Call LoadDbValues(RsOld)
		If Rs.Eof Then
			EditRow = False ' Update Failed
		Else

			' Field bh
			Call xwlm.bh.SetDbValue(Rs, xwlm.bh.CurrentValue, Null, xwlm.bh.ReadOnly)

			' Field lmmc
			Call xwlm.lmmc.SetDbValue(Rs, xwlm.lmmc.CurrentValue, Null, xwlm.lmmc.ReadOnly)

			' Field lmmc2
			Call xwlm.lmmc2.SetDbValue(Rs, xwlm.lmmc2.CurrentValue, Null, xwlm.lmmc2.ReadOnly)

			' Field px
			Call xwlm.px.SetDbValue(Rs, xwlm.px.CurrentValue, Null, xwlm.px.ReadOnly)

			' Field urllb
			Call xwlm.urllb.SetDbValue(Rs, xwlm.urllb.CurrentValue, Null, xwlm.urllb.ReadOnly)

			' Check recordset update error
			If Err.Number <> 0 Then
				FailureMessage = Err.Description
				Rs.Close
				Set Rs = Nothing
				EditRow = False
				Exit Function
			End If
			Dim bValidMasterRecord, sMasterFilter, RsMaster, KeyValue

			' Call Row Updating event
			bUpdateRow = xwlm.Row_Updating(RsOld, Rs)
			If bUpdateRow Then

				' Clone new recordset object
				Set RsNew = ew_CloneRs(Rs)

				' Cascade Update detail tables if necessary
				EditRow = xwlm.UpdateDetailRecords(RsOld, RsNew)
				If EditRow Then
					Rs.Update
				End If
				If Err.Number <> 0 Or Not EditRow Then
					If Err.Description <> "" Then FailureMessage = Err.Description
					EditRow = False
				Else
					EditRow = True
				End If
				If EditRow Then
				End If
			Else
				Rs.CancelUpdate

				' Set up error message
				If SuccessMessage <> "" Or FailureMessage <> "" Then

					' Use the message, do nothing
				ElseIf xwlm.CancelMessage <> "" Then
					FailureMessage = xwlm.CancelMessage
					xwlm.CancelMessage = ""
				Else
					FailureMessage = Language.Phrase("UpdateCancelled")
				End If
				EditRow = False
			End If
		End If

		' Call Row Updated event
		If EditRow Then
			Call xwlm.Row_Updated(RsOld, RsNew)
		End If
		Rs.Close
		Set Rs = Nothing
		If IsObject(RsOld) Then
			RsOld.Close
			Set RsOld = Nothing
		End If
		If IsObject(RsNew) Then
			RsNew.Close
			Set RsNew = Nothing
		End If
	End Function

	' -----------------------------------------------------------------
	' Add record
	'
	Function AddRow(RsOld)
		If Not EW_DEBUG_ENABLED Then On Error Resume Next
		Dim Rs, sSql, sFilter
		Dim RsNew
		Dim bInsertRow
		Dim RsChk
		Dim sIdxErrMsg

		' Clear any previous errors
		Err.Clear
		Dim RsMaster, sMasterUserIdMsg, sMasterFilter, bCheckMasterRecord

		' Set up foreign key field value from Session
		If xwlm.CurrentMasterTable = "bhlm" Then
			xwlm.bh.CurrentValue = xwlm.bh.SessionValue
		End If
		Dim bValidMasterRecord

		' Load db values from rsold
		If Not IsNull(RsOld) Then
			Call LoadDbValues(RsOld)
		End If

		' Add new record
		sFilter = "(0 = 1)"
		xwlm.CurrentFilter = sFilter
		sSql = xwlm.SQL
		Set Rs = Server.CreateObject("ADODB.Recordset")
		Rs.CursorLocation = EW_CURSORLOCATION
		Rs.Open sSql, Conn, 1, EW_RECORDSET_LOCKTYPE
		Rs.AddNew
		If Err.Number <> 0 Then
			Message = Err.Description
			Rs.Close
			Set Rs = Nothing
			AddRow = False
			Exit Function
		End If

		' Field bh
		Call xwlm.bh.SetDbValue(Rs, xwlm.bh.CurrentValue, Null, (xwlm.bh.CurrentValue&"" = ""))

		' Field lmmc
		Call xwlm.lmmc.SetDbValue(Rs, xwlm.lmmc.CurrentValue, Null, False)

		' Field lmmc2
		Call xwlm.lmmc2.SetDbValue(Rs, xwlm.lmmc2.CurrentValue, Null, False)

		' Field px
		Call xwlm.px.SetDbValue(Rs, xwlm.px.CurrentValue, Null, (xwlm.px.CurrentValue&"" = ""))

		' Field urllb
		Call xwlm.urllb.SetDbValue(Rs, xwlm.urllb.CurrentValue, Null, (xwlm.urllb.CurrentValue&"" = ""))

		' Check recordset update error
		If Err.Number <> 0 Then
			FailureMessage = Err.Description
			Rs.Close
			Set Rs = Nothing
			AddRow = False
			Exit Function
		End If

		' Call Row Inserting event
		bInsertRow = xwlm.Row_Inserting(RsOld, Rs)
		If bInsertRow Then

			' Clone new recordset object
			Set RsNew = ew_CloneRs(Rs)
			Rs.Update
			If Err.Number <> 0 Then
				FailureMessage = Err.Description
				AddRow = False
			Else
				AddRow = True
			End If
			If AddRow Then
			End If
		Else
			Rs.CancelUpdate

			' Set up error message
			If SuccessMessage <> "" Or FailureMessage <> "" Then

				' Use the message, do nothing
			ElseIf xwlm.CancelMessage <> "" Then
				FailureMessage = xwlm.CancelMessage
				xwlm.CancelMessage = ""
			Else
				FailureMessage = Language.Phrase("InsertCancelled")
			End If
			AddRow = False
		End If
		Rs.Close
		Set Rs = Nothing
		If AddRow Then
			xwlm.lmid.DbValue = RsNew("lmid")
		End If
		If AddRow Then

			' Call Row Inserted event
			Call xwlm.Row_Inserted(RsOld, RsNew)
		End If
		If IsObject(RsNew) Then
			RsNew.Close
			Set RsNew = Nothing
		End If
	End Function

	' -----------------------------------------------------------------
	' Set up Master Detail based on querystring parameter
	'
	Sub SetUpMasterParms()
		Dim bValidMaster, sMasterTblVar

		' Hide foreign keys
		sMasterTblVar = xwlm.CurrentMasterTable
		If sMasterTblVar = "bhlm" Then
			xwlm.bh.Visible = False
			If bhlm.EventCancelled Then xwlm.EventCancelled = True
		End If
		DbMasterFilter = xwlm.MasterFilter '  Get master filter
		DbDetailFilter = xwlm.DetailFilter ' Get detail filter
	End Sub

	' Page Load event
	Sub Page_Load()

		'Response.Write "Page Load"
	End Sub

	' Page Unload event
	Sub Page_Unload()

		'Response.Write "Page Unload"
	End Sub

	' Page Redirecting event
	Sub Page_Redirecting(url)

		'url = newurl
	End Sub

	' Message Showing event
	' typ = ""|"success"|"failure"|"warning"
	Sub Message_Showing(msg, typ)

		' Example:
		'If typ = "success" Then
		'	msg = "your success message"
		'ElseIf typ = "failure" Then
		'	msg = "your failure message"
		'ElseIf typ = "warning" Then
		'	msg = "your warning message"
		'Else
		'	msg = "your message"
		'End If

	End Sub

	' Page Render event
	Sub Page_Render()

		'Response.Write "Page Render"
	End Sub

	' Page Data Rendering event
	Sub Page_DataRendering(header)

		' Example:
		'header = "your header"

	End Sub

	' Page Data Rendered event
	Sub Page_DataRendered(footer)

		' Example:
		'footer = "your footer"

	End Sub

	' Form Custom Validate event
	Function Form_CustomValidate(CustomError)

		'Return error message in CustomError
		Form_CustomValidate = True
	End Function
End Class
%>
