/*********************************************************************
 **
 **   server/appx-client-ilf-editor.js - ILF Editor routines
 **
 **   This module contains code for the Appx ILF editor.
 **
 *********************************************************************/

var	ilfEditorMode = false;
var ilfAddorChangeMode = false;
var ilfClipboardText = "";

var	ilfSelecting = false;
var	ilfSelection = false;
var	ilfRespecify = false;

var ilfRelativePagePosition = 0;
var ilfStartingPagePosition = 0;
var ilfFirstRowSnapshot = null;
var ilfFirstSelectedRow = 3;
var ilfLastSelectedRow = ilfFirstSelectedRow;
var ilfIsLastPage = false;

var ilfScanDataReady = false;
var ilfScanOrgValue = null;

// For easy lookup, we'll use this map container to get 
//  the option number for an option literal 
// NOTE: The OPT_ are defined in appx-client-keys.js
var textOptionNums = new Map();
textOptionNums.set('ENTER', OPT_ENTER);
textOptionNums.set('CANCEL', OPT_CAN);
textOptionNums.set('RETURN', OPT_ENTER);
textOptionNums.set('END', OPT_END);
textOptionNums.set('SCAN', OPT_SCAN);
// For easy lookup, we'll use this map container 
//  to get the colors for text in the the Ilf editor
var ilfTextColors = new Map();
ilfTextColors.set('green', "rgb(0,128,0)");
ilfTextColors.set('red', "rgb(128,0,0)");
ilfTextColors.set('blue', "rgb(0,0,235)");
ilfTextColors.set('brown', "rgb(128,128,0)");
ilfTextColors.set('purple', "rgb(128,0, 128)");
ilfTextColors.set('teal', "rgb(0,128, 128)");
ilfTextColors.set('pink', "rgb(255,235,235)");


function appxCheckForIlfEditorMode(mode) {
	ilfEditorMode = false;

	// We'll check here to see if we need to be in ILF edit mode
	if ((Math.abs(mode & M_SHOW) != 0) ||
		(Math.abs(mode == M_COMPARE))) {
	
		// Look for the box that has the ILF editor title bar information
		var box = appxfindbox(1, 1, 1, parseInt(appxLoginFormCols, 10), true);
		if (box !== null) {
			
			var leftBracket = box.data.lastIndexOf("(");
			var nameEndIndex = 0;
			var nameStartIndex = 0;
			
			for ( nameEndIndex = leftBracket - 1;
				  nameEndIndex >= 0 && box.data[nameEndIndex] == ' ';
				  nameEndIndex-- ) {
				// Search for the end of the process type name
			}
			
			for ( nameStartIndex = nameEndIndex;
				  nameStartIndex >= 0 && box.data[nameStartIndex] != ' ';
				  nameStartIndex-- ) {
				// Search for the start of the process type name
			}

			if ( (leftBracket - nameEndIndex) == 3 ) {
				// Get the process type name then make sure it is one we handle
				var processType = box.data.substring(nameStartIndex + 1, nameEndIndex + 1);
				if ( processType == "Menu" || processType == "Job" || processType == "Input" ||
					 processType == "Output" || processType == "Update" || processType == "Query" ||
					 processType == "Inquiry" || processType == "Status" || processType == "Subroutine" ||
					 processType == "Action" || processType == "File" || processType == "Table_Src" ) {
						 
					ilfEditorMode = true;
					
					if (debug) {
						var processName = box.data.substring(new String("@ST=").length, nameStartIndex); 
						processName = processName.trim();
						console.log("ILF Editing a \"%s\" process named \"%s\"", processType, processName);
					}
				}
			}
		}
	}
}

async function ilfGetClipboardContents() {
  try {
    const text = await navigator.clipboard.readText();
	ilfClipboardText = text;
	if (debug) { console.log('ilfGetClipboardContents: %s', ilfClipboardText); }
  } catch (err) {
    console.error('ilfSetClipboardContents failed: ', err);
  }
}

async function ilfSetClipboardContents(clipboardText) {
  try {
	// Remove the 'space/n' sent by the engine 
	clipboardText = clipboardText.replace(/ \n/g, '');
	ilfClipboardText = clipboardText;  
	await navigator.clipboard.writeText(clipboardText);
	if (debug) { console.log('ilfSetClipboardContents: %s', clipboardText); }
  } catch (err) {
	console.error('ilfSetClipboardContents failed: ', err);
  }
}

function appxIlfAutoGuiButtonClick(event) {
	// We'll process any Ilf Editor auto gui button clicks here before passing them along
	var option = $(this).prop('id').substring(11);
	var buttonlabel = $(this).text().toLowerCase();
	if (!ilfSelecting && ((option == 2 && (buttonlabel == "cut" || buttonlabel == "move")) ||
		(option == 3 && (buttonlabel == "copy")) || option == 7)) { /* "Cut", "Move", "Copy", "Select" or "Respecify Range" buttons were clicked */ 
		ilfSelecting = true;	
		if (buttonlabel != "respecify range") {	
			var pos = appxGetCursorPos();
			ilfFirstSelectedRow = ilfLastSelectedRow = pos.row + 1;
			ilfStartingPagePosition = ilfRelativePagePosition;
			ilfFirstRowSnapshot = JSON.stringify(appx_session.current_show.boxes[pos.row].rowtext);
		} else {
			ilfRespecify = true; 
		}
	} else if (ilfSelecting && (buttonlabel == "respecify range")) {	
		ilfRespecify = true;
		ilfSelection = false;	
	} else if (!ilfSelection && (option == 304)) { /* "Current Line" button was clicked */ 
		ilfSelection = true;
	} else if (ilfSelecting && ((option == 2 && (buttonlabel == "cut" || buttonlabel == "move")) || 
			   (option == 3 && (buttonlabel == "copy")) || option == 4 || option == 5 ||	/* "Cut", "Move", "Copy", "Delete", "Comment", "Uncomment" */  
				option == 6 || option == 304 || option == 278)) { 							/* "Current Line" or "Cancel Select" buttons were clicked */ 
		var pos = appxGetCursorPos();
		ilfFirstSelectedRow = ilfLastSelectedRow = pos.row + 1;
		ilfStartingPagePosition = 0;
		ilfFirstRowSnapshot = null;
		ilfSelecting = ilfSelection = ilfRespecify = false;
	}
	
	appxwidgetcallback2(option);
}

function appxGenerateAutoGuiButtons(box, boxIdx, cellSizes) {

	// Auto buttons are generated from screen text
	// that matches the following format:
	//
	// {label}) {text}
	//
	// Where {label} is one or two numeric digits or the literals
	// ENTER, CANCEL, RETURN, END, or SCAN.
	// Then there is a ") " paren and at least one space.
	// Then the {text} is the button label.
	//
	// There are two ways to define auto buttons.  With the
	// above format, the button will be one row in size and
	// the width is determined by parsing for the start of the
	// {label} and the end of the {text}.
	//
	// The second way uses the same format, but if you use
	// an INVERSE and ULINE characteristic combination, the
	// extends of the button are determined by the extends
	// of the characteristic region.
	//
	// Note: The above comments can be found in and, were taken
	// 		 from the function 'void genButtons()' in the 
	//		 java client source file Display.java       
	//
	// The version uses regular expressions to parse the 
	// option command literal(s) and the button lable. 
	//
	// Currently, this version doesn't support parsing the  
	// INVERSE and ULINE characteristic combination information.
	//
	
	var autoButtonData = [];	
	const regex = /[0-9]{1,3}(?=\)\s([\w\s\/]+)([\s]+))|ENTER(?=\)\s([\w\s\/]+)([\s])+)|CANCEL(?=\)\s([\w\s\/]+)([\s])+)|RETURN(?=\)\s([\w\s\/]+)([\s])+)|END(?=\)\s([\w\s\/]+)([\s])+)|SCAN(?=\)\s([\w\s\/]+)([\s])+)/gmi
	var ilfShortcuts = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";  
	var ilfUsedShortcuts = "";  
	
	for (var j = 0; j < box.rowtext.length; j++) {
		var rawdata = new String(box.rowtext[j].string) + ' ';
		var matches = rawdata.matchAll(regex);
		for (const match of matches) {
			var buttonOpt = match[0].trim();
			buttonOpt = isNaN(buttonOpt) == false ? buttonOpt : textOptionNums.get((buttonOpt.toUpperCase()));
			// We'll blank out the button option number from the row text to ensure it doesn't show from behind the new button
			var spaces = new Array(match[0].length + 1).join(' ');
			box.rowtext[j].string = box.rowtext[j].string.replace(match[0], spaces);
			
			var buttonOptStart = match.index;
			buttonOptStart += (buttonOpt.length > 1 ? buttonOpt.length - 1 : 0);
			var buttonOptEnd = match.index + match[0].length;
			var idx = 1;
			for (; idx < match.length; idx++) {
				if (match[idx] !== undefined)
					break;
			}
			var spacesAfterName = match[idx].split(" ").length;
			var buttonName = match[idx].trim();
			
			// We'll blank out the button name from the row text to ensure it doesn't show from behind the new button
			spaces = new Array(match[idx].length + 1).join(' ');
			box.rowtext[j].string = box.rowtext[j].string.replace(match[idx], spaces);
			var buttonNameStart = buttonOptEnd + 2;
			var buttonNameEnd = buttonNameStart + buttonName.length;
			
			autoButtonData.push({boxIdx: boxIdx, rowTextIdx: j, buttonOpt: buttonOpt, buttonOptStart: buttonOptStart, buttonOptEnd: buttonOptEnd, buttonName: buttonName, buttonShortcut: "", buttonLength: buttonNameEnd - buttonOptStart, spacesAfterName: spacesAfterName, buttonNameStart: buttonNameStart, buttonNameEnd: buttonNameEnd});
		}	
	}
	
	if (autoButtonData.length > 0) {
		// Mark this box as having auto gui buttons
		box.hasAutoGuiButtons = true;
		// If there are no widgets, this is the main ILF editor display otherwise, it's the ILF editor toolbox
		if (box.widgets.length == 0) {
			// Used later, setting this to a space means this box doesn't have a title
			box.widget.wLabel = (box.isAuditBox === undefined) ? "" : box.widget.wLabel;
			// Before we add our button html, clear the underline attribute  
			for (var idx = 0; idx < box.rowtext.length; idx++) {
				box.rowtext[idx].uline = false;
			}
		}

		// Make the buttons in each column the same size as the largest button in that column then add a shortcut key for each button
		// Note:  Adding the shortcuts here is rather convoluted and would be better done inline within
		//        the auto gui button detection loop however, to better emulate the ADC results its necessary.
		//        Also, as noted elsewhere, IE and Chromium based browsers reserve certain ALT+{key} combinations for themselves
		//        thus some shortcuts keys may only work if they are used in combination with the SHIFT key {e.g., ALT+SHIFT+E}
		for (const button of autoButtonData) {
			var newSize = button.buttonLength;
			// Check for a second row with a button in this column
			for (var i = 0; i < autoButtonData.length; i++) {
				// Skip ourself
				if (button.rowTextIdx == autoButtonData[i].rowTextIdx) {
					// If needed, add a shortcut key for this button
					if (button.buttonShortcut == '') {
						for (var idx = 0; idx < button.buttonName.length && button.buttonShortcut == ''; idx++) {
							if( ilfShortcuts.indexOf(button.buttonName.charAt(idx)) >= 0 &&
								ilfUsedShortcuts.indexOf(button.buttonName.charAt(idx)) < 0 ) {
								button.buttonShortcut = button.buttonName.charAt(idx);
							}
						}
						if (button.buttonShortcut != '') { ilfUsedShortcuts += button.buttonShortcut; }
					}
					continue;
				}
				if (button.rowTextIdx != autoButtonData[i].rowTextIdx && button.buttonNameStart == autoButtonData[i].buttonNameStart) {
					// Make the size the the first and second rows of this column the same
					newSize = Math.max(button.buttonLength, autoButtonData[i].buttonLength);
					button.buttonLength = autoButtonData[i].buttonLength = newSize;
					// If needed, add a shortcut key for this button
					if (autoButtonData[i].buttonShortcut == '') {
						for (var idx = 0; idx < autoButtonData[i].buttonName.length && autoButtonData[i].buttonShortcut == ''; idx++) {
							if( ilfShortcuts.indexOf(autoButtonData[i].buttonName.charAt(idx)) >= 0 &&
								ilfUsedShortcuts.indexOf(autoButtonData[i].buttonName.charAt(idx)) < 0 ) {
								autoButtonData[i].buttonShortcut = autoButtonData[i].buttonName.charAt(idx);
							}
						}
						if (autoButtonData[i].buttonShortcut != '') { ilfUsedShortcuts += autoButtonData[i].buttonShortcut; }
					}
					// Check for a third row with a button in this column
					var j = i+1;
					for (; j < autoButtonData.length; j++) {
						if (((button.rowTextIdx != autoButtonData[j].rowTextIdx) && (autoButtonData[i].rowTextIdx != autoButtonData[j].rowTextIdx)) &&
							((button.buttonNameStart == autoButtonData[j].buttonNameStart) && (autoButtonData[i].buttonNameStart == autoButtonData[j].buttonNameStart))) {
							// Make the size the the first, second and third rows of this column the same
							newSize = Math.max(autoButtonData[i].buttonLength, autoButtonData[j].buttonLength);
							button.buttonLength = autoButtonData[j].buttonLength = autoButtonData[i].buttonLength = newSize;
							// If needed, add a shortcut key for this button
							if (autoButtonData[j].buttonShortcut == '') {
								for (var idx = 0; idx < autoButtonData[j].buttonName.length && autoButtonData[j].buttonShortcut == ''; idx++) {
									if( ilfShortcuts.indexOf(autoButtonData[j].buttonName.charAt(idx)) >= 0 &&
										ilfUsedShortcuts.indexOf(autoButtonData[j].buttonName.charAt(idx)) < 0 ) {
										autoButtonData[j].buttonShortcut = autoButtonData[j].buttonName.charAt(idx);
									}
								}
								if (autoButtonData[j].buttonShortcut != '') { ilfUsedShortcuts += autoButtonData[j].buttonShortcut; }
							}							
						}	
					}
				}
			}		
		}

		var divboxcss = "appx--box";
		var divboxstyle = "width: 100%;";
		
		var divdatacss = "appx-data";
		
		if (debug) console.log(`Auto GUI Buttons:`);
		for (const button of autoButtonData) {
			if (debug) {
				console.log(`Option: ${button.buttonOpt}, Start ${button.buttonOptStart} End ${button.buttonOptEnd}`);
				console.log(`Name: ${button.buttonName}, Shortcut "${button.buttonShortcut}" Start ${button.buttonNameStart} End ${button.buttonNameEnd}`);
			}

			// Prepare the html for the button	
			var buttonName = "";
			var buttonShortcut = button.buttonShortcut;
			for (var k = 0; k < button.buttonName.length; k++) {
				if (k == button.buttonName.indexOf(buttonShortcut)) {
					buttonName += "<span class=\"accesskeyunderline\">";
					buttonName += button.buttonName[k];
					buttonName += "</span>";
				} else {
					buttonName += button.buttonName[k];
				}
			}
			var accessKey = `accesskey=\"${button.buttonShortcut.toUpperCase()}\"`;
			var buttonWidth = button.buttonLength * cellSizes.w; 
			var buttonLeft = button.buttonOptStart * cellSizes.w;
			var buttonstyle = `margin: 0px; padding: 0px; position: absolute; left: ${buttonLeft}px; height: ${cellSizes.h}px; width: ${buttonWidth}px; font-size: 12px; z-index: 990;`;
			var optionNum = button.buttonOpt;
			var buttoncss = `button appx-border appx-border-bevel-raised appxwidget ilf-autogui-button appx-shortcut-${optionNum}`;
			var newButtonHtml = appx_session.getProp("showOptionNumbers") ? 
				`<button type=\"button\" class=\"${buttoncss}\" style=\"${buttonstyle}\" id=\"widget_sac_${optionNum}\"><span class=\"appx-option\">${optionNum}</span><div class=\"${divboxcss}\" style=\"${divboxstyle}\"><div class=\"${divdatacss}\" ${accessKey}>${buttonName}</div></div></button>` 
					:						
				`<button type=\"button\" class=\"${buttoncss}\" style=\"${buttonstyle}\" id=\"widget_sac_${optionNum}\"><div class=\"${divboxcss}\" style=\"${divboxstyle}\"><div class=\"${divdatacss}\" ${accessKey}>${buttonName}</div></div></button>`;	
		
			// Insert the new button html
			box.rowtext[parseInt(button.rowTextIdx, 10)].string += newButtonHtml;	
		}
	}
}

function appxIlfEditorInquireModeAddRowtext(box, idx, rowtxt, colorvalue, isRowCommented, isVerbLabel, isVerbReturn) {
	var ilfEngineOffset = (appx_session._isServerUnicode == true) ? 0 : -1; 
	var ilfFlags = "";
	var ilfComment = "";
	var ilfVerb = "";
	// First, if we don't have it yet, get what could be the ILF flags and verb
	if (box.rowtext.length > 2 && ilfVerb == "") {
		if (box.rowtext[0].size_cols == 5) { ilfFlags = box.rowtext[0].string; } 
		if (box.rowtext[0].size_cols == 1) { ilfComment = box.rowtext[0].string; } 
		if (box.rowtext[1].size_cols == 1) { ilfComment = box.rowtext[1].string; } 
		if (box.rowtext[1].size_cols == 8) { ilfVerb = box.rowtext[1].string; } 
		if (box.rowtext[2].size_cols == 8) { ilfVerb = box.rowtext[2].string; } 
		isVerbLabel = ilfVerb.startsWith("LABEL") || ilfVerb.startsWith("GOSUB") || ilfVerb.startsWith("GOTO") ? true : false;
		isVerbReturn = !isVerbLabel && (ilfVerb.startsWith("RETURN") || ilfVerb.startsWith("END")) ? true : false;
	}
	// Any verb text longer than 8 here and this isn't a line of ILF code
	if (ilfVerb.length <= 8) {
		// For the 'AT FIELD', 'BLANK', 'BLINK', 'BOLD', 'BRIGHT', 'COLOR', 'DIM', 'DISPLAY', 'ENABLE', 'FONT', 'INVERSE', 'NO BOLD', 'NO ULINE'
		// 'OK INPUT', 'NORMAL', 'PICTURE', 'POSITION' and 'ULINE' verbs, we need to add fields to hold the '(AT APPEARENCE #' & the trailing ')'
		if ((ilfVerb.startsWith("AT FIELD") || ilfVerb.startsWith("BLANK") || ilfVerb.startsWith("BLINK") ||
			 ilfVerb.startsWith("BOLD") || ilfVerb.startsWith("BRIGHT") || ilfVerb.startsWith("COLOR") ||
			 ilfVerb.startsWith("DIM") || ilfVerb.startsWith("DISPLAY") || ilfVerb.startsWith("ENABLE") ||
			 ilfVerb.startsWith("FONT") || ilfVerb.startsWith("INVERSE") || ilfVerb.startsWith("NO BOLD") ||
			 ilfVerb.startsWith("NO INPUT") || ilfVerb.startsWith("NO ULINE") || ilfVerb.startsWith("OK INPUT") ||
			 ilfVerb.startsWith("NORMAL") || ilfVerb.startsWith("PICTURE") || ilfVerb.startsWith("POSITION") || 
			 ilfVerb.startsWith("ULINE")) && box.rowtext.length == 7 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "(AT APPEARENCE #";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col + box.rowtext[5 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = ")";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[7 + ilfEngineOffset].pos_col + box.rowtext[7 + ilfEngineOffset].size_cols;
			box.rowtext.splice(8 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'BEG LOOP' verb, we need to add fields to hold the '=', 'TO' and 'STEP'
		if (ilfVerb.startsWith("BEG LOOP") && box.rowtext.length == 7 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[4 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(4 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "TO";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[6 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "STEP";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[8 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(8 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'BEG READ' verb, we need to add fields to hold the 'HOLD' and 'KEY IS'
		if (ilfVerb.startsWith("BEG READ") && box.rowtext.length == 7 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "HOLD";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[4 + ilfEngineOffset].pos_col + box.rowtext[4 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "KEY IS";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[6 + ilfEngineOffset].pos_col + box.rowtext[6 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(7 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'CALC' verb, we need to add a field to hold the '='
		if (ilfVerb.startsWith("CALC") && box.rowtext.length == 5 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "=";
			newrowtxt.pos_col = box.rowtext[3 + ilfEngineOffset].pos_col + box.rowtext[3 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(4 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'CALL' verb, we need to add fields to hold the 'RESIDENT?', 'END?" and 'FAIL'  
		if (ilfVerb.startsWith("CALL") && box.rowtext.length == 9 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "RESIDENT?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[6 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "END?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[8 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(8 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[10 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(10 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'CLOSE' verb, we need to add a field to hold the 'PHYSICAL?'
		if (ilfVerb.startsWith("CLOSE") && box.rowtext.length == 6 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "PHYSICAL?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[4 + ilfEngineOffset].pos_col + box.rowtext[4 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'LOGOUT' verb, we need to add a field to hold the 'SYSTEM?'
		if ((ilfVerb.startsWith("LOGOUT")) && box.rowtext.length == 4 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "SYSTEM?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[2 + ilfEngineOffset].pos_col + box.rowtext[2 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(3 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'CNV BIN', 'CNV PORT' or 'CNV TEXT' verbs, we need to add a field to hold the '='
		if ((ilfVerb.startsWith("CNV BIN") || ilfVerb.startsWith("CNV PORT") || ilfVerb.startsWith("CNV TEXT")) && box.rowtext.length == 9 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col + box.rowtext[5 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'CREATE' or 'OPEN' verbs, we need to add fields to hold the 'SHARE?', 'FAIL" and 'CACHE' or 'CACHE?'  
		if ((ilfVerb.startsWith("CREATE") || ilfVerb.startsWith("OPEN")) && box.rowtext.length == 8 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "SHARE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[7 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(7 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = ilfVerb.startsWith("CREATE") ? "CACHE" : "CACHE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[9 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(9 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'INPUT', 'INQUIRY', 'JOB', 'MENU', 'OUTPUT', 'QUERY', 'RUN', 'STATUS', 'SUBR' or 'UPDATE' verbs
		//	we need to add fields to hold the 'END?' and 'FAIL'
		if ((ilfVerb.startsWith("INPUT") || ilfVerb.startsWith("INQUIRY") || ilfVerb.startsWith("JOB") ||
			 ilfVerb.startsWith("MENU") || ilfVerb.startsWith("OUTPUT") || ilfVerb.startsWith("QUERY") ||
			 ilfVerb.startsWith("RUN") || ilfVerb.startsWith("STATUS") || ilfVerb.startsWith("SUBR") ||
			 ilfVerb.startsWith("UPDATE")) && box.rowtext.length == 8 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "END?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[6 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[8 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(8 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'PASS' verb, we need to add a field to hold the 'SHARE?'
		if (ilfVerb.startsWith("PASS") && box.rowtext.length == 8 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "SHARE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[7 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(7 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'READ', 'READNEXT' and 'READPREV' verbs, we need to add fields to hold the 'HOLD', 'FT" and 'BY'  
		if (ilfVerb.startsWith("READ") && box.rowtext.length == 8 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "HOLD";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[4 + ilfEngineOffset].pos_col + box.rowtext[4 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FT";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[6 + ilfEngineOffset].pos_col + box.rowtext[6 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(7 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "BY";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[8 + ilfEngineOffset].pos_col + box.rowtext[8 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(9 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'RECEIVE' verb, we need to add a field to hold the 'REQ?'
		if (ilfVerb.startsWith("RECEIVE") && box.rowtext.length == 8 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "REQ?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[7 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(7 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'REWRITE' verb, we need to add a field to hold the 'FAIL'
		if ((ilfVerb.startsWith("REWRITE")) && box.rowtext.length == 6 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.pos_col = box.rowtext[4 + ilfEngineOffset].pos_col + box.rowtext[4 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'SCAN' verb, we need to add a field to hold the '='
		if (ilfVerb.startsWith("SCAN") && box.rowtext.length == 9 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col + box.rowtext[5 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'SCRATCH' verb, we need to add fields to hold the 'FAIL' and 'CACHE?'
		if (ilfVerb.startsWith("SCRATCH") && box.rowtext.length == 7 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "CACHE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[7 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(7 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'SELECT' verb, we need to add a field to hold the 'KEY IS'
		if (ilfVerb.startsWith("SELECT") && box.rowtext.length == 6 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "KEY IS";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col - (newrowtxt.size_cols + 2);
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'SET' verb, we need to add a field to hold the '='
		if (ilfVerb.startsWith("SET") && box.rowtext.length == 9 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col + box.rowtext[5 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'SET TEMP' verb, we need to add fields to hold the 'AT', 'FOR' and 'OF'
		if (ilfVerb.startsWith("SET TEMP") && box.rowtext.length == 11 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "AT";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[3 + ilfEngineOffset].pos_col + box.rowtext[3 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(4 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FOR";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col + box.rowtext[5 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "OF";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[9 + ilfEngineOffset].pos_col + box.rowtext[9 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(10 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'DEL ALL' or 'IF EXIST' or 'WRITE' verbs, we need to add a field to hold the 'FAIL'
		if ((ilfVerb.startsWith("DEL ALL") || ilfVerb.startsWith("IF EXIST") || ilfVerb.startsWith("WRITE")) && box.rowtext.length == 6 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length + 1;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col - (newrowtxt.size_cols);
			box.rowtext.splice(5 + ilfEngineOffset, 0, newrowtxt);
		}
		// For the 'VERIFY' verb, we need to add fields to hold the 'TYPE' and 'FAIL'
		if (ilfVerb.startsWith("VERIFY") && box.rowtext.length == 8 + ilfEngineOffset) {
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.string = "TYPE";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[5 + ilfEngineOffset].pos_col + box.rowtext[5 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(6 + ilfEngineOffset, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.rowtext[7 + ilfEngineOffset].pos_col + box.rowtext[7 + ilfEngineOffset].size_cols + 1;
			box.rowtext.splice(8 + ilfEngineOffset, 0, newrowtxt);
		}
		
		if (idx == 0 && (ilfFlags.charAt(0) == '*' || ilfFlags.charAt(0) == 'C' || ilfComment.charAt(0) == '*' || ilfVerb.charAt(0) == '*' || rowtxt.string.charAt(0) == '*')) {
			isRowCommented = true;
			colorvalue = ilfTextColors.get(("green"));
		} else if (idx == 0 && (ilfVerb.startsWith("LABEL") || rowtxt.string.startsWith("LABEL"))) {
			ilfVerb = rowtxt.string.startsWith("LABEL") ? rowtxt.string : ilfVerb;
			isVerbLabel = true;
			colorvalue = ilfTextColors.get(("brown"));
		} else if (idx == 0 && ilfFlags.length > 0) {
			colorvalue = ilfTextColors.get(("red"));
		} else if (idx > 1 + ilfEngineOffset && ilfVerb.startsWith("LABEL") && isRowCommented) {
			colorvalue = ilfTextColors.get(("green"));
		} else if ((idx == 2 + ilfEngineOffset && ilfVerb.startsWith("LABEL")) || idx > 2 + ilfEngineOffset && isVerbLabel && !isRowCommented) {
			isVerbLabel = true;
			colorvalue = ilfTextColors.get(("brown"));
		} else if ((idx == 2 + ilfEngineOffset && !isRowCommented && ilfVerb.length != 0) ||
				 (idx == 2 + ilfEngineOffset && !isRowCommented && ilfVerb.length == 0 &&
				 (rowtxt.string == "COMMIT" || rowtxt.string == "END" || rowtxt.string == "END PROC" ||
				  rowtxt.string == "EXIT" || rowtxt.string == "TRAP"))) {
			colorvalue = ilfTextColors.get(("blue"));
		} else if (idx == 3 + ilfEngineOffset && (rowtxt.string.startsWith("SYSTEM?")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx == 4 + ilfEngineOffset && (rowtxt.string.startsWith("=") ||
							  rowtxt.string.startsWith("AT"))) {
			colorvalue = "inherit";
		} else if (idx == 4 + ilfEngineOffset && (ilfVerb.startsWith("CALL") || ilfVerb.startsWith("PASS")) &&
								(box.rowtext[idx - 1].string.length == 0) && !isRowCommented) {
			// A 'CALL' or 'PASS' verbs without an application ID
			colorvalue = ilfTextColors.get(("teal"));
		} else if (idx == 5 + ilfEngineOffset && (rowtxt.string.startsWith("=") || rowtxt.string.startsWith("HOLD") || rowtxt.string.startsWith("FAIL") ||
								rowtxt.string.startsWith("SHARE?") || rowtxt.string.startsWith("PHYSICAL?") || rowtxt.string.startsWith("KEY IS")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx == 6 + ilfEngineOffset && (rowtxt.string.startsWith("(AT APPEARENCE #") || rowtxt.string.startsWith("END?") ||	rowtxt.string.startsWith("TO") ||
								rowtxt.string.startsWith("FOR") || rowtxt.string.startsWith("RESIDENT?") ||	rowtxt.string.startsWith("TYPE") ||
								rowtxt.string.startsWith("=")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx == 7 + ilfEngineOffset && (rowtxt.string.startsWith("FT") || rowtxt.string.startsWith("KEY IS") ||	rowtxt.string.startsWith("FAIL") ||
								rowtxt.string.startsWith("SHARE?") || rowtxt.string.startsWith("REQ?") || rowtxt.string.startsWith("CACHE?")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx == 8 + ilfEngineOffset && ((ilfVerb.startsWith("AT FIELD") || ilfVerb.startsWith("BLANK") || ilfVerb.startsWith("BLINK") ||
								 ilfVerb.startsWith("BOLD") || ilfVerb.startsWith("BRIGHT") || ilfVerb.startsWith("COLOR") ||
								 ilfVerb.startsWith("DIM") || ilfVerb.startsWith("DISPLAY") || ilfVerb.startsWith("ENABLE") ||
								 ilfVerb.startsWith("FONT") || ilfVerb.startsWith("INVERSE") || ilfVerb.startsWith("NO BOLD") ||
								 ilfVerb.startsWith("NO ULINE") || ilfVerb.startsWith("OK INPUT") || ilfVerb.startsWith("NORMAL") ||
								 ilfVerb.startsWith("PICTURE") || ilfVerb.startsWith("POSITION") || ilfVerb.startsWith("ULINE"))
								 && rowtxt.string.startsWith(")") ||
								rowtxt.string.startsWith("END?") || rowtxt.string.startsWith("FAIL") ||	rowtxt.string.startsWith("STEP")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx == 8 + ilfEngineOffset && (ilfVerb.startsWith("AND") || ilfVerb.startsWith("APPEND") || ilfVerb.startsWith("CNV BIN") ||
								ilfVerb.startsWith("COMPUTE") || ilfVerb.startsWith("DATE ADD") || ilfVerb.startsWith("IF") ||
								ilfVerb.startsWith("OR") ||	ilfVerb.startsWith("SET")) && 
								(box.rowtext[idx - 1].string.length == 0) && !isRowCommented) {
			// A 'AND', 'APPEND', 'CNV BIN', 'COMPUTE', 'DATE ADD', 'IF', 'OR' or 'SET' verb without a source application ID
			colorvalue = ilfTextColors.get(("teal"));
		} else if (idx == 9 + ilfEngineOffset && (rowtxt.string.startsWith("BY") || rowtxt.string.startsWith("FAIL") || rowtxt.string.startsWith("CACHE")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx == 10 + ilfEngineOffset && (rowtxt.string.startsWith("OF") || rowtxt.string.startsWith("FAIL")) && !isRowCommented) {
			colorvalue = "inherit";
		} else if (idx >= 2 + ilfEngineOffset && !isRowCommented && !isVerbLabel && !isVerbReturn) {
			colorvalue = ilfTextColors.get(("red"));
		} else if (!isRowCommented && isVerbLabel) {
			colorvalue = ilfTextColors.get(("brown"));
		} else if (!isRowCommented && isVerbReturn) {
			colorvalue = ilfTextColors.get(("red"));
		} else if (!isRowCommented) {
			colorvalue = "inherit";
		} else if (isRowCommented) {
			colorvalue = ilfTextColors.get(("green"));
		}
	}

	return Object.freeze({ colorvalue:colorvalue, isRowCommented:isRowCommented, isVerbLabel:isVerbLabel, isVerbReturn:isVerbReturn });
}

function appxFlagsFieldChanged(event) {
	// To emulate the ADC, we need to observe the data entry into the flags field of the target row so we can dynamically change
	// the colors of the input and text fields depending on whether a comment character is entered or removed.
	// As a bonus, we’ll also ensure that only valid characters are entered into the field to avoid unnecessary trips to the server.
	var id = $(this).prop('id');
	var content = $(this).val();
	var newchar = String.fromCharCode(event.charCode || event.keyCode);
	var rownum = parseInt(id.substring(id.lastIndexOf("_") + 1), 10);
	var position = $('#'+id)[0].selectionStart;
	if (event.type == "keyup") { 
		// When the comment characters are removed we need to change the text color of all the fields in the row
		if ((!content.includes('*', 0) && !content.toUpperCase().includes('C', 0) && event.key != "Tab") ||
			((content.includes('*', 0) || content.toUpperCase().includes('C', 0)) && content.length <= 1) &&
			event.key == "Backspace" || event.key == "Delete") { 
			$('#'+id).css({"color": "inherit"});
			$('#'+id+"~ input").css({"color": ilfTextColors.get(("red"))}); 
			$("#rowtext_1_"+rownum.toString()).css({"color": "inherit"});
			$("#rowtext_1_"+rownum.toString()+"~ div").css({"color": ilfTextColors.get(("blue"))});
			var ilfVerb = $("#rowtext_1_"+rownum.toString()).text();
			if (ilfVerb.length > 0 && (ilfVerb.startsWith("GOSUB") || ilfVerb.startsWith("GOTO"))) {
				$("#rowtext_1_"+rownum.toString()+"~ input").css({"color": ilfTextColors.get(("brown"))});
			}
			// A 'AND', 'APPEND', 'CNV BIN', 'CNV PORT', 'CNV TEXT', 'COMPUTE', 'DATE ADD', 'IF', 'OR' or 'SET' verbs without a source application ID				
			if (ilfVerb.length > 0 && 
				(ilfVerb.startsWith("AND") || ilfVerb.startsWith("APPEND") || ilfVerb.startsWith("CNV BIN") ||
				 ilfVerb.startsWith("CNV PORT") || ilfVerb.startsWith("CNV TEXT") || ilfVerb.startsWith("COMPUTE") ||
				 ilfVerb.startsWith("DATE ADD") || ilfVerb.startsWith("IF") || ilfVerb.startsWith("OR") ||
				 ilfVerb.startsWith("SET")) && ($("#appxitem_50_"+rownum.toString()).text().length == 0)) {
				$("#appxitem_50_"+rownum.toString()+"~ input").css({"color": ilfTextColors.get(("teal"))});
			}
		}
		return;
	} 
	// The flag field can only accept 'T', 'F' and '-' as well as the comment characters '*' or 'C'.
	// In addition, the comment characters can only be entered into the first position of the flag field
	if ((content.length == 0 && position == 0 && newchar != "*" && newchar.toUpperCase() != "C" &&
		 newchar.toUpperCase() != "T" && newchar.toUpperCase() != "F" && newchar != "-") || 
		(content.length > 0 && position > 0 && content[0] != "*" && content[0].toUpperCase() != "C" && 
		 newchar.toUpperCase() != "T" && newchar.toUpperCase() != "F" && newchar != "-")) {  
		event.preventDefault();
		return;
	}
	// When the comment characters are entered or are already present we need to change the text color of all the fields in the row
	if ((newchar == "*" || newchar.toUpperCase() == "C") || (content.includes("*") || content.toUpperCase().includes("C"))) {
		$('#'+id).css({"color": ilfTextColors.get(("green"))});
		$('#'+id+"~ input").css({"color": ilfTextColors.get(("green"))});
		$("#rowtext_1_"+rownum.toString()).css({"color": ilfTextColors.get(("green"))});
		$("#rowtext_1_"+rownum.toString()+"~ div").css({"color": ilfTextColors.get(("green"))});
	}
}

function appxSourceAppIdFieldChanged(event) {
	// To emulate the ADC, we need to observe the data entry into the source application field of the target row so we can dynamically change
	// the colors of the source input field depending on whether any characters are entered or the last character removed.
	var id = $(this).prop('id');
	var content = $(this).val();
	// When the last character is removed we need to change the color of the source input field
	if (event.type == "keyup") { 
		if (content.length == 0) { 
			$('#'+id+"~ input").css({"color": ilfTextColors.get(("teal"))});
		}
		return;
	} 
	// Any characters in the source application and we need to change the color of the source input field
	$('#'+id+"~ input").css({"color": ilfTextColors.get(("red"))});
}

function appxIlfEditorChangeModeAddRowtext(box, colorvalue) {
	var ilfEngineOffset = (appx_session._isServerUnicode == true) ? 0 : -1; 
	var ilfFlags = "";
	var ilfComment = "";	
	var ilfVerb = "";
	// A sanity check since screens other than Ilf code will pass this way
	if (box.rowtext[0] == undefined) { return; }
	// We'll get a chunk of row text so we can clone it later
	var rowtxt = box.rowtext[0];
	for (var idx = box.items.length - 1; idx >= 0; idx--) {
		var item = box.items[idx][0];
		// First, if we don't have it yet, get what could be the ILF flags and verb
		if (box.items.length > 2 && ilfVerb == "") {
			ilfFlags = box.items[box.items.length - 1][0].data;
			ilfComment = box.items[box.items.length - (2 + ilfEngineOffset)][0].data;
			ilfVerb = box.items[box.items.length - (3 + ilfEngineOffset)][0].data;
			
			// Add a 'keypress' and a 'keyup' handler to the flags field along with the uppercase property	
			// Note: without 'keyup' we won't see the special keys like backspace
			var tag = box.items[box.items.length - 1][1];
			if (tag !== null) {	tag.on("keypress", box.items.length, appxFlagsFieldChanged); }
			if (tag !== null) {	tag.on("keyup", box.items.length, appxFlagsFieldChanged); }
			if (tag !== null) {	tag.css("text-transform", "uppercase"); }
		}
		
		// For comments or verbs that are commented, starting with "*" and "C", the sibling item(s) are a text input which need to have the text colored green
		// For all other verbs, the sibling item{s) text input too but are colored red when they are created in appx-client-widget.js
		if (ilfComment.charAt(0) == '*' || (item.data.startsWith("C") || item.data.startsWith("*") && ilfVerb.startsWith(""))) {
			// When the box has more than two items then the comment starts in the flags field and the verb needs to be green too
			if (box.items.length > 2) {	box.rowtext[0].colorvalue = ilfTextColors.get(("green")); }
			for (; idx >= 0; idx--) {
				var tag = box.items[idx][1];
				if (tag !== null) { tag.css({"color": ilfTextColors.get(("green"))}); tag.css({"text-transform": "none"}); }
			}
			break;
		}
		// For the 'AT FIELD', 'BLANK', 'BLINK', 'BOLD', 'BRIGHT', 'COLOR', 'DIM', 'DISPLAY', 'ENABLE', 'FONT', 'INVERSE', 'NO BOLD', 'NO ULINE'
		// 'OK INPUT', 'NORMAL', 'PICTURE', 'POSITION' and 'ULINE' verbs, we need to add fields to hold the '(AT APPEARENCE #' & the trailing ')'
		if ((ilfVerb.startsWith("AT FIELD") || ilfVerb.startsWith("BLANK") || ilfVerb.startsWith("BLINK") ||
			 ilfVerb.startsWith("BOLD") || ilfVerb.startsWith("BRIGHT") || ilfVerb.startsWith("COLOR") ||
			 ilfVerb.startsWith("DIM") || ilfVerb.startsWith("DISPLAY") || ilfVerb.startsWith("ENABLE") ||
			 ilfVerb.startsWith("FONT") || ilfVerb.startsWith("INVERSE") || ilfVerb.startsWith("NO BOLD") ||
			 ilfVerb.startsWith("NO INPUT") || ilfVerb.startsWith("NO ULINE") || ilfVerb.startsWith("OK INPUT") ||
			 ilfVerb.startsWith("NORMAL") || ilfVerb.startsWith("PICTURE") || ilfVerb.startsWith("POSITION") || 
			 ilfVerb.startsWith("ULINE")) && box.items.length == 7 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "(AT APPEARENCE #";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = ")";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col + box.items[0][0].size_cols;
			box.rowtext.splice(2, 0, newrowtxt);
			break;
		}
		// For the 'BEG LOOP' verb, we need to add fields to hold the '=', 'TO' and 'STEP'
		if (ilfVerb.startsWith("BEG LOOP") && box.items.length == 7 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[2][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "TO";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(2, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "STEP";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(3, 0, newrowtxt);
			break;
		}
		// For the 'BEG READ' verb, we need to add fields to hold the 'HOLD' and 'KEY IS'
		if (ilfVerb.startsWith("BEG READ") && box.items.length == 7 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "HOLD";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[2][0].pos_col + box.items[2][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "KEY IS";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(2, 0, newrowtxt);
			break;
		}
		// For the 'CALC' verb, we need to add a field to hold the '='
		if (ilfVerb.startsWith("CALC") && box.items.length == 5 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "=";
			newrowtxt.pos_col =  box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'CALL' verb, we need to add fields to hold the 'RESIDENT?', 'END?" and 'FAIL'  
		if (ilfVerb.startsWith("CALL") && box.items.length == 9 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "RESIDENT?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[2][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "END?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(2, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(3, 0, newrowtxt);
			break;
		}
		// For the 'CLOSE' verb, we need to add a field to hold the 'PHYSICAL?'
		if (ilfVerb.startsWith("CLOSE") && box.items.length == 6 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "PHYSICAL?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'LOGOUT' verb, we need to add a field to hold the 'SYSTEM?'
		if ((ilfVerb.startsWith("LOGOUT")) && box.items.length == 4 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "SYSTEM?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'CNV BIN', 'CNV PORT' or 'CNV TEXT' verbs, we need to add a field to hold the '='
		if ((ilfVerb.startsWith("CNV BIN") || ilfVerb.startsWith("CNV PORT") || ilfVerb.startsWith("CNV TEXT")) && box.items.length == 9 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[3][0].pos_col + box.items[3][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			// Add a 'keypress' and a 'keyup' handler to the source application id field	
			// Note: without 'keyup' we won't see the special keys like backspace
			var tag = tag = box.items[idx - (6 + ilfEngineOffset)][1];
			if (tag !== null) {	tag.on("keypress", box.items.length, appxSourceAppIdFieldChanged); }
			if (tag !== null) {	tag.on("keyup", box.items.length, appxSourceAppIdFieldChanged); }
			// A 'CNV BIN', 'CNV PORT' or 'CNV TEXT' verbs without a source application ID				
			if (box.items[idx - (6 + ilfEngineOffset)][0].data == "") {
				tag = box.items[idx - (7 + ilfEngineOffset)][1];
				if (tag !== null) { tag.css({"color": ilfTextColors.get(("teal"))}); }
			}
			break;
		}
		// For the 'CREATE' or 'OPEN' verbs, we need to add fields to hold the 'SHARE?', 'FAIL" and 'CACHE' or 'CACHE?'  
		if ((ilfVerb.startsWith("CREATE") || ilfVerb.startsWith("OPEN")) && box.items.length == 8 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "SHARE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[2][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(2, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = ilfVerb.startsWith("CREATE") ? "CACHE" : "CACHE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(3, 0, newrowtxt);
			break;
		}
		// For the 'INPUT', 'INQUIRY', 'JOB', 'MENU', 'OUTPUT', 'QUERY', 'RUN', 'STATUS', 'SUBR' or 'UPDATE' verbs
		// we need to add fields to hold the 'END?' and 'FAIL'
		if ((ilfVerb.startsWith("INPUT") || ilfVerb.startsWith("INQUIRY") || ilfVerb.startsWith("JOB") ||
			 ilfVerb.startsWith("MENU") || ilfVerb.startsWith("OUTPUT") || ilfVerb.startsWith("QUERY") ||
			 ilfVerb.startsWith("RUN") || ilfVerb.startsWith("STATUS") || ilfVerb.startsWith("SUBR") ||
			 ilfVerb.startsWith("UPDATE")) && box.items.length == 8 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "END?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(2, 0, newrowtxt);
			break;
		}
		// For the 'PASS' verb, we need to add a field to hold the 'SHARE?'
		if (ilfVerb.startsWith("PASS") && box.items.length == 8 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "SHARE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'READ', 'READNEXT' and 'READPREV' verbs, we need to add fields to hold the 'HOLD', 'FT" and 'BY'  
		if (ilfVerb.startsWith("READ") && box.items.length == 8 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "HOLD";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[3][0].pos_col + box.items[3][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FT";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[2][0].pos_col + box.items[2][0].size_cols + 1;
			box.rowtext.splice(2, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "BY";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(3, 0, newrowtxt);
			break;
		}
		// For the 'RECEIVE' verb, we need to add a field to hold the 'REQ?'
		if (ilfVerb.startsWith("RECEIVE") && box.items.length == 8 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "REQ?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'REWRITE' verb, we need to add a field to hold the 'FAIL'
		if ((ilfVerb.startsWith("REWRITE")) && box.items.length == 6 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'SCAN' or 'SET' or 'SET TOT' verbs, we need to add a field to hold the '='
		if ((ilfVerb.startsWith("SCAN") || ilfVerb.startsWith("SET")) && box.items.length == 9 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "=";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[3][0].pos_col + box.items[3][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			// Add a 'keypress' and a 'keyup' handler to the source application id field	
			// Note: without 'keyup' we won't see the special keys like backspace
			var tag = tag = box.items[idx - (6 + ilfEngineOffset)][1];
			if (tag !== null) {	tag.on("keypress", box.items.length, appxSourceAppIdFieldChanged); }
			if (tag !== null) {	tag.on("keyup", box.items.length, appxSourceAppIdFieldChanged); }
			// A 'SET' verb without a source application ID				
			if (box.items[idx - (6 + ilfEngineOffset)][0].data == "") {
				tag = box.items[idx - (7 + ilfEngineOffset)][1];
				if (tag !== null) { tag.css({"color": ilfTextColors.get(("teal"))}); tag.css({"text-transform": "none"}); }
			}
			break;
		}
		// For the 'SCRATCH' verb, we need to add fields to hold the 'FAIL' and 'CACHE?'
		if (ilfVerb.startsWith("SCRATCH") && box.items.length == 7 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "CACHE?";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 1);
			box.rowtext.splice(2, 0, newrowtxt);
			break;
		}
		// For the 'SELECT' verb, we need to add a field to hold the 'KEY IS'
		if (ilfVerb.startsWith("SELECT") && box.items.length == 6 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "KEY IS";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols + 2);
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'SET TEMP' verb, we need to add fields to hold the 'AT', 'FOR' and 'OF'
		if (ilfVerb.startsWith("SET TEMP") && box.items.length == 11 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "AT";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[7][0].pos_col + box.items[7][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FOR";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[6][0].pos_col + box.items[6][0].size_cols + 1;
			box.rowtext.splice(2, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "OF";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[3][0].pos_col + box.items[3][0].size_cols + 1;
			box.rowtext.splice(3, 0, newrowtxt);
			// Add a 'keypress' and a 'keyup' handler to the source application id field	
			// Note: without 'keyup' we won't see the special keys like backspace
			var tag = tag = box.items[idx - (8 + ilfEngineOffset)][1];
			if (tag !== null) {	tag.on("keypress", box.items.length, appxSourceAppIdFieldChanged); }
			if (tag !== null) {	tag.on("keyup", box.items.length, appxSourceAppIdFieldChanged); }
			// A 'SET' verb without a source application ID				
			if (box.items[idx - (8 + ilfEngineOffset)][0].data == "") {
				tag = box.items[idx - (9 + ilfEngineOffset)][1];
				if (tag !== null) { tag.css({"color": ilfTextColors.get(("teal"))}); tag.css({"text-transform": "none"}); }
			}
			break;
		}
		// For the 'DEL ALL' or 'IF EXIST' or 'WRITE' verbs, we need to add a field to hold the 'FAIL'
		if ((ilfVerb.startsWith("DEL ALL") || ilfVerb.startsWith("IF EXIST") || ilfVerb.startsWith("WRITE")) && box.items.length == 6 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length + 1;
			newrowtxt.pos_col = box.items[0][0].pos_col - (newrowtxt.size_cols);
			box.rowtext.splice(1, 0, newrowtxt);
			break;
		}
		// For the 'VERIFY' verb, we need to add fields to hold the 'TYPE' and 'FAIL'
		if (ilfVerb.startsWith("VERIFY") && box.items.length == 8 + ilfEngineOffset && box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			var newrowtxt = JSON.parse(JSON.stringify(rowtxt));
			newrowtxt.colorvalue = colorvalue;
			newrowtxt.string = "TYPE";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[2][0].pos_col + box.items[2][0].size_cols + 1;
			box.rowtext.splice(1, 0, newrowtxt);
			newrowtxt = JSON.parse(JSON.stringify(newrowtxt));
			newrowtxt.string = "FAIL";
			newrowtxt.size_cols = newrowtxt.string.length;
			newrowtxt.pos_col = box.items[1][0].pos_col + box.items[1][0].size_cols + 1;
			box.rowtext.splice(2, 0, newrowtxt);
			break;
		}
		// These verbs don't need any fields added but they do need their color set
		if (((ilfVerb.startsWith("APPEND") || ilfVerb.startsWith("AND") || ilfVerb.startsWith("BEG AT") ||
			  ilfVerb.startsWith("CANCEL") || ilfVerb.startsWith("COMMIT") || ilfVerb.startsWith("COMPUTE") || 
			  ilfVerb.startsWith("COPY") || ilfVerb.startsWith("DATE ADD") || ilfVerb.startsWith("DATE BTW") ||
			  ilfVerb.startsWith("DELETE") || ilfVerb.startsWith("END") || ilfVerb.startsWith("END AT") ||
			  ilfVerb.startsWith("END LOOP") || ilfVerb.startsWith("END PROC") || ilfVerb.startsWith("END READ") ||
			  ilfVerb.startsWith("ERROR") || ilfVerb.startsWith("EXIT") || ilfVerb.startsWith("EXITREAD") ||
			  ilfVerb.startsWith("GOSUB") || ilfVerb.startsWith("GOTO") || ilfVerb.startsWith("IF") ||
			  ilfVerb.startsWith("LOCAL") || ilfVerb.startsWith("MESSAGE") || ilfVerb.startsWith("OR") ||
			  ilfVerb.startsWith("OVERFLOW") || ilfVerb.startsWith("POP") || ilfVerb.startsWith("PUSH") ||
			  ilfVerb.startsWith("REFRESH") || ilfVerb.startsWith("RESTORE") || ilfVerb.startsWith("RETURN") ||
			  ilfVerb.startsWith("ROLLBACK") || ilfVerb.startsWith("SAVEPNT") || ilfVerb.startsWith("SET DATE") ||
			  ilfVerb.startsWith("SET DAY") || ilfVerb.startsWith("SET MNTH") || ilfVerb.startsWith("STORE") ||
			  ilfVerb.startsWith("SQL") || ilfVerb.startsWith("TIMEOUT") || ilfVerb.startsWith("TOTAL") ||
			  ilfVerb.startsWith("TRAP") || ilfVerb.startsWith("USE CC") || ilfVerb.startsWith("WARNING") ||
			  (box.rowtext[0].string == "COMMIT" || box.rowtext[0].string == "END" || box.rowtext[0].string == "END PROC" ||
			   box.rowtext[0].string == "EXIT" || box.rowtext[0].string == "TRAP")) &&
			  (ilfComment.charAt(0) != '*' && !ilfFlags.startsWith("C") && !ilfFlags.startsWith("*"))) &&  box.rowtext.length == 2 + ilfEngineOffset) {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("blue"));
			// For the verbs 'GOSUB and 'GOTO' the sibling item(s) are a text input which need to have the text colored brown
			if (ilfVerb.startsWith("GOSUB") || ilfVerb.startsWith("GOTO")) {
				for (; idx >= 0; idx--) {
					var tag = box.items[idx][1];
					if (tag !== null) { tag.css({"color": ilfTextColors.get(("brown"))}); }
				}
			}
			// A 'AND', 'APPEND', 'COMPUTE', 'DATE ADD', 'DATE BTW', 'IF', 'OR', 'SET DAY', 'SET MNTH' or 'TOTAL' verb without a source application ID				
			if (((ilfVerb.startsWith("AND") || ilfVerb.startsWith("APPEND") || ilfVerb.startsWith("COMPUTE") ||
				 ilfVerb.startsWith("DATE ADD") || ilfVerb.startsWith("DATE BTW") || ilfVerb.startsWith("IF") ||
				 ilfVerb.startsWith("OR") || ilfVerb.startsWith("SET DAY") || ilfVerb.startsWith("SET MNTH") ||
				 ilfVerb.startsWith("TOTAL")) && box.items.length == 10 + ilfEngineOffset)) {
				// Add a 'keypress' and a 'keyup' handler to the source application id field	
				// Note: without 'keyup' we won't see the special keys like backspace
				var tag = tag = box.items[idx - (7 + ilfEngineOffset)][1];
				if (tag !== null) {	tag.on("keypress", box.items.length, appxSourceAppIdFieldChanged); }
				if (tag !== null) {	tag.on("keyup", box.items.length, appxSourceAppIdFieldChanged); }
				if (box.items[idx - (7 + ilfEngineOffset)][0].data == "") {
					tag = box.items[idx - (8 + ilfEngineOffset)][1];
					if (tag !== null) { tag.css({"color": ilfTextColors.get(("teal"))}); tag.css({"text-transform": "none"}); }
				}
			}
			// The 'TIMEOUT' verb without a source application ID				
			if ((ilfVerb.startsWith("TIMEOUT")) && box.items.length == 7 + ilfEngineOffset) {
				// Add a 'keypress' and a 'keyup' handler to the source application id field	
				// Note: without 'keyup' we won't see the special keys like backspace
				var tag = tag = box.items[idx - (4 + ilfEngineOffset)][1];
				if (tag !== null) {	tag.on("keypress", box.items.length, appxSourceAppIdFieldChanged); }
				if (tag !== null) {	tag.on("keyup", box.items.length, appxSourceAppIdFieldChanged); }
				if (box.items[idx - (4 + ilfEngineOffset)][0].data == "") {
					tag = box.items[idx - (5 + ilfEngineOffset)][1];
					if (tag !== null) { tag.css({"color": ilfTextColors.get(("teal"))}); tag.css({"text-transform": "none"}); }
				}
			}
			break;
		}
		// The 'LABEL' verb doesn't need any fields added but the fields do need the color set
		if (ilfComment.startsWith("LABEL") || box.rowtext[0].string == "LABEL") {
			box.rowtext[1 + ilfEngineOffset].colorvalue = ilfTextColors.get(("brown"));
			for (; idx >= 0; idx--) {
				var tag = box.items[idx][1];
				if (tag !== null) { tag.css({"color": ilfTextColors.get(("brown"))}); }
			}
			break;
		}
		
	}
}
