Ext.define("IceCap.view.Window", {
	extend: "Ext.window.Window",

	layout: "fit",

	requires: [
		"IceCap.controller.Window"
	],

	config: {
		inputData: null,
		lastTabIndex: 1,
		currentTabIndex: 1,
		content: null,
		keyArea: null,
		working: false,
		needFocus: 1,
		currentPosition: {
			col: 1,
			lin: 1
		},
		statusBar: null,
		main: null,
		sessionValue: "",
		cursor: null,
		timer: null,
		theme: "",
		requestCallBack: Ext.emptyFn,
		responseCallBack: Ext.emptyFn,
		enterOnDblClick: false,
		marker: null,
		markerActive: false,
		options: {},
		typeMode: 1
	},

	closable: false,

	modal: false,

	controller: "icecap.view.window",

	listeners: {
		afterrender: {
			fn: function(i_panel) {

				var i_self = i_panel;

				i_self.addKeyEvents();

				var i_content = i_self.getContent();

				if (i_content) {

					var o_inputData = i_self.getInputData();

					var a_fields = IceCap.util.Handler.getInputFields(i_content);
					var b_found = false;
					var b_error = false;

					Ext.Array.each(a_fields, function(i_field) {
						if (i_field.getTabIndex() === i_self.getNeedFocus()) {
							if (!b_error) {
								setTimeout(function() {
									i_field.focus(false, 10);
								}, 10);
							}
							b_found = true;

							return false;
						}
					});

					if (!b_found) {

						i_self.setCurrentPosition({
							col: 2,
							lin: 1
						});

						if (!b_error) {
							setTimeout(function() {
								i_self.focus(true, 10);
							}, 10);
						}
					}
				}
			},
			buffer: 100
		},
		dblclick: {
			fn: "onDblClick",
			element: "body"
		},
		click: {
			fn: "onClick",
			element: "body"
		},
		wheel: {
			fn: "onWheel",
			element: "body"
		},
		fieldoption: {
			fn: function(a_config) {

				var i_self = this;
				var i_controller = i_self.getController();

				var o_data = {};

				Ext.apply(o_data, {
					key: "ENTER"
				});

				Ext.Array.each(a_config, function(o_config) {

					var s_field = o_config.field;

					o_data[s_field] = o_config.option;

					Ext.apply(o_data, {
						csrCol: o_config.col,
						csrLin: o_config.lin
					});
				});

				i_self.setCurrentPosition({
					col: o_data.csrCol,
					lin: o_data.csrLin
				});

				i_controller.onSendData({
					func: ""
				}, o_data);
			}
		},
		key: {
			fn: function(s_value) {

				var i_self = this;
				var i_controller = i_self.getController();

				i_controller.doKeyEvent(s_value);
			}
		}

	},

	onKeyDown: Ext.emptyFn, // THIS IS NEEDED TO OVERRIDE Ext.util.Floating

	initComponent: function() {

		var i_self = this;

		var o_params = Ext.Object.fromQueryString(window.location.search);

		Ext.Object.each(o_params, function(s_key, value) {
			o_params[s_key] = Ext.decode(value, true) || value;
		});

		var o_options = Ext.apply(i_self.options, o_params.options || {});

		Ext.apply(i_self, {
			theme: i_self.theme || o_params.theme || ""
		});

		i_self.callParent(arguments);

		i_self.setTypeMode(IceCap.util.Handler.typeMode.INSERT);

		i_self.add(i_self.createLayout());

		i_self.enableBubble([
			"onAddWebContainer",
			"toWindow",
			"applicationClose"
		]);

		i_self.recreate();
	},

	createStatusBar: function() {

		var i_self = this;

		var i_statusbar = Ext.widget("toolbar", {
			dock: "bottom",
			cls: "icecap-statusbar",
			hidden: false,
			ui: "statusbar",
			height: 30,
			layout: {
				type: "hbox",
				align: "top"
			},
			items: [
				{
					xtype: "label",
					itemId: "icecap-message",
					listeners: {
						afterrender: {
							fn: function(i_label) {

								var i_tpl = Ext.create("Ext.XTemplate",
									"<ul style=\"list-style: none;",
												"margin:10px;",
												"padding:0;",
									"\">",
										"<tpl for=\".\">",
											"<li>{text}</li>",
										"</tpl>",
									"</ul>"
								);

								Ext.create("Ext.tip.ToolTip", {
									target: i_label.getEl(),
									html: "",
									anchor: true,
									defealtAlign: "b50-t50",
									listeners: {
										beforeshow: {
											fn: function (i_tip) {

												var b_hasError = i_label.hasCls("icecap-statusbar-error");

												var o_inputData = i_self.getInputData();

												var a_messages = Ext.Array.from(o_inputData.message);

												if (b_hasError && a_messages.length > 0) {
													var s_value = i_tpl.apply(a_messages);
													i_tip.update(s_value);
												}
												else {
													return b_hasError;
												}
											}
										}
									}
								});
							}
						},
						click: {
							element: "el",
							fn: function (i_event, i_element) {

								var o_input = {
									col: 3,
									lin: 24
								};

								i_self.setCurrentPosition(o_input);

								var i_cursor = i_self.getCursor();
								i_cursor.moveCursor(o_input);

								i_self.doKeyEvent("F1");
							}
						},
					}
				},
				"->",
				{
					xtype: "label",
					itemId: "icecap-position"
				},
				{
					xtype: "label",
					text: " INS",
					itemId: "icecap-typemode"
				}
			],
			setText: function (s_text) {

				var i_toolbar = this;

				var i_message = i_toolbar.getComponent("icecap-message");

				if (i_message) {
					i_message.setText(s_text);
				}
			}
		});

		return i_statusbar;
	},

	createLayout: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		return i_self.createContent();
	},

	createContent: function() {

		var i_self = this;

		var i_panel = Ext.widget("panel", {
			layout: {
				type: "vbox",
				align: "stretch"
			},
			cls: ["icecap-window", i_self.getTheme()].join("-"),
			border: false,
			focusable: true,
			tabIndex: -1,
			items: i_self.createItems()
		});

		i_self.setMain(i_panel);

		return i_panel;
	},

	createItems: function() {

		var i_self = this;

		var o_inputData = i_self.getInputData();

		var a_items = [];

		var i_keyArea = Ext.widget("panel", {
			layout: {
				type: "column"
			},
			border: false,
			focusable: false,
			minHeight: 50,
			height: null,
			defaults: {
				margin: "0 5 5 0"
			},
			cls: ["icecap-panel", i_self.getTheme()].join("-"),
			ui: "icecap-keyarea"
		});

		var i_center = Ext.widget("form", {
			border: false,
			layout: "absolute",
			flex: 1,
			ui: ["icecap", i_self.getTheme()].filter(Boolean).join("-")
		});

		a_items.push(i_center);
		a_items.push(i_keyArea);

		i_self.setContent(i_center);

		var i_statusbar = i_self.createStatusBar();

		i_self.addDocked([
			i_statusbar
		]);


		i_self.setStatusBar(i_statusbar);
		i_self.setKeyArea(i_keyArea);

		i_self.updateMessage(o_inputData);

		return a_items;
	},

	createFields: function () {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_fields = [];

		var n_tabIndex = 1;
		var n_focus = o_inputData.focus;

		var n_inputWidth = o_inputData.width || 80;

		var a_sliced = Ext.Array.from(o_inputData.input || []);

		Ext.Array.each(a_sliced, function (o_config, n_index) {

			var n_width = (IceCap.util.Handler.getWidth(o_config.len) + (IceCap.util.Handler.getWidth() / 2));

			var o_meta = o_config.metaData || {};

			var o_field = {
				inputType: "text",
				xtype: "textfield",
				ui: "icecap-field"
			};

			var s_type = o_field.xtype || "textfield";
			var n_x = IceCap.util.Handler.getX(o_config.col) - 3;
			var n_y = IceCap.util.Handler.getY(o_config.lin);
			var b_password = o_config.atr == "27";

			if (o_config.len > n_inputWidth) {
				var n_temp = n_inputWidth - o_config.col;
				n_width = (IceCap.util.Handler.getWidth(n_temp) + (IceCap.util.Handler.getWidth() / 2));
			}


			if (o_config.hasOwnProperty("colsize") && o_config.hasOwnProperty("rows")) {

				var s_data = o_config.dta || "";

				o_field.xtype = s_type = "textarea";
				o_field.height = IceCap.util.Handler.getHeight() * o_config.rows;
				o_field.preventScrollbars = true;

				var a_split = s_data.split("\n");

				var s_result = "";

				var n_split = a_split.length;

				Ext.Array.each(a_split, function (s_part, n_index) {

					var regex = new RegExp(".{" + o_config.colsize + "}", "g");

					var a_match = s_part.match(regex);

					if (a_match) {
						s_result += s_part;
					}
					else {
						if (n_index != n_split - 1) {
							s_result += s_part + "\n";
						}
						else {
							s_result += s_part;
						}
					}
				});

				o_config.dta = s_result;


				o_field.getSubmitValue = function () {

					var i_field = this;

					var s_value = i_field.stripReturns(i_field.getRawValue());

					var regex = new RegExp(".{1," + o_config.colsize + "}", "g");

					var a_split = s_value.match(regex) || [];

					return a_split.join("\n");
				};

			}

			var o_listeners = Ext.apply({}, o_meta.listeners);
			delete o_meta.listeners;

			var a_field = ["icecap-field", i_self.getTheme()];

			var a_pass = [b_password ? "iceCap-input-password" : "iceCap-input-" + (o_config.atr || 20)];

			a_pass.push(i_self.getTheme());

			var a_cls = [a_field.filter(Boolean).join("-"), a_pass.filter(Boolean).join("-")];

			var s_cls = a_cls.join(" ");

			if (isNaN(n_x)) {
				n_x = IceCap.util.Handler.getColSize();
			}

			if (isNaN(n_y)) {
				n_y = IceCap.util.Handler.getLineHeight();
			}

			var s_ui = b_password ? "icecap-password-field" : "icecap-field";

			if (!o_meta.xtype) {
				Ext.apply(o_field, i_self.applyFFW(o_config));
			}

			var i_field;

			var s_name = IceCap.util.Handler.getRandomName();

			if (o_field.readOnly) {

				o_field.xtype = s_type = "displayfield";
				s_ui = "icecap-display";
				s_cls = (["iceCap-output-" + (o_config.atr || 20), i_self.getTheme()].filter(Boolean).join("-"));

				o_field = {
					autoEl: {
						tag: "span"
					},
					html: o_config.dta || "",
					x: n_x,
					y: n_y,
					name: s_name,
					cls: ["x-form-display-field-icecap-display", s_cls].join(" "),
					style: {
						"white-space": "pre"
					},
					listeners: {
						afterrender: {
							fn: function (i_field) {
								i_field.el.dom.setAttribute("draggable", false);
							}
						}
					}
				};

				if (o_config.atr == "27") {
					o_field.hidden = true;
				}

				if (o_config.atr == "22") {

					Ext.apply(o_field.style, {
						"font-size": (IceCap.util.Handler.getFontSize() - 1) + "px",
						"font-weight": "bold;",
						"letter-spacing": (IceCap.util.Handler.getColSize() - IceCap.util.Handler.getBoldColSize()) + "px",
						"word-spacing": "0.02em;"
					});
				}

				i_field = Ext.widget("component", o_field);

			}
			else {

				Ext.Object.merge(o_field, {
					width: n_width,
					enforceMaxLength: true,
					maxLength: o_config.len,
					minWidth: IceCap.util.Handler.getDefaultWidth(),
					tabIndex: !o_field.readOnly ? n_tabIndex : -1,
					focusable: !o_field.readOnly,
					lin: o_config.lin,
					col: o_config.col,
					emuId: o_config.id,
					value: o_config.dta || "",
					itemId: o_config.id,
					name: s_name,
					inputAttrTpl: "spellcheck=false autocomplete=\"new-password\" name=\"" + s_name + "\"",
					x: n_x,
					y: n_y,
					cls: s_cls,
					enableKeyEvents: true,
					selectOnFocus: false,
					ui: s_ui,
					listeners: {
						afterrender: {
							fn: function (i_field) {

								if (i_field.inputEl && !i_field.metaField) {

									if (i_field.xtype == "textarea") {
										i_field.inputEl.dom.setAttribute("rows", o_config.rows);
									}

									if (i_field.getTabIndex() === i_self.getNeedFocus()) {

										i_field.focus(false, 10, function () {
											var o_inputData = i_self.getInputData();

											var s_value = i_field.getValue();
											var n_col = i_field.col;
											var n_diff = 0;

											if (n_col < o_inputData.csrCol) {
												n_diff = o_inputData.csrCol - n_col;
												i_field.inputEl.el.dom.selectionEnd = i_field.inputEl.el.dom.selectionStart = i_field.inputEl.el.dom.selectionStart + n_diff;
											}

											var o_position = {
												col: o_inputData.csrCol,
												lin: o_inputData.csrLin
											};

											i_self.setCurrentPosition(o_position);

											var i_cursor = i_self.getCursor();
											i_cursor.moveCursor(o_position);
											i_cursor.hide();
										});
									}
								}
							}
						},
						change: {
							fn: function (i_field, value) {

								var s_direction = i_field.inputEl.el.dom.selectionDirection;

								var n_curpos = s_direction == "forward" ? i_field.inputEl.el.dom.selectionEnd : i_field.inputEl.el.dom.selectionStart;

								value = value || "";

								if (value.length == i_field.maxLength && n_curpos == i_field.maxLength) {
									i_self.doNavigationKey(1, true);
								}
							}
						},
						focus: {
							fn: function (i_field) {

								var n_tabIndex = i_field.getTabIndex();
								i_self.setCurrentTabIndex(n_tabIndex);

								var o_position = {
									col: i_field.col,
									lin: i_field.lin
								};
								i_self.setCurrentPosition(o_position);

								var i_cursor = i_self.getCursor();
								i_cursor.moveCursor(o_position);
								i_cursor.hide();
							}
						},
						keyup: {
							fn: function (i_field, i_event) {

								if (i_field.xtype === "textfield") {

									var value = i_field.getValue();

									var s_direction = i_field.inputEl.el.dom.selectionDirection;

									var n_start = s_direction == "forward" ? i_field.inputEl.el.dom.selectionEnd : i_field.inputEl.el.dom.selectionStart;
									var n_add = value.length * IceCap.util.Handler.getWidth();

									if (n_start != value.length) {
										n_add = n_start * IceCap.util.Handler.getWidth();
									}

									var o_input = Ext.apply({
										x: i_field.getLocalX() + n_add,
										y: i_field.getLocalY()
									});

									var o_position = IceCap.util.Handler.toColAndLine(o_input);
									i_self.setCurrentPosition(o_position);

									var i_cursor = i_self.getCursor();
									i_cursor.moveCursor(o_position);
								}
							}
						},
						keydown: {
							fn: function (i_field, i_event) {

								var i_regext = new RegExp("^\\w{1}$");

								var value = i_field.getValue();

								if (i_event.ctrlKey) {

									var o_input = {};
									var o_position = {};
									var o_box = {};
									var i_main = i_self.getMain();
									var i_cursor = i_self.getCursor();
									var a_inputs = IceCap.util.Handler.getInputFields(i_self);
									var b_intersect = false;
									var n_selection = 0;

									var i_inputEl = i_field.inputEl;

									if (i_event.keyCode == Ext.event.Event.DOWN ||
										i_event.keyCode == Ext.event.Event.UP) {

										n_selection = i_inputEl.dom.selectionEnd;

										i_event.stopEvent();

										o_position = {
											col: i_field.col + n_selection,
											lin: i_field.lin
										};

										if (i_event.keyCode == Ext.event.Event.DOWN) {
											o_position.lin++;
										}
										else {
											o_position.lin--;
										}

										i_self.setCurrentPosition(o_position);

										i_cursor.moveCursor(o_position);

										o_input = {
											x: IceCap.util.Handler.getX(o_position.col),
											y: IceCap.util.Handler.getY(o_position.lin)
										};

										Ext.apply(o_box, {
											width: i_cursor.getWidth(),
											height: i_cursor.getHeight()
										}, o_input);

										Ext.Array.each(a_inputs, function (i_field) {

											var o_bound = i_field.el.dom.getBoundingClientRect();

											var o_rect = Ext.apply({}, {
												x: i_field.getLocalX(),
												y: i_field.getLocalY(),
												width: o_bound.width,
												height: o_bound.height
											});

											if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
												b_intersect = true;
												i_field.focus(false, 10);
												return false;
											}
										});

										if (!b_intersect) {

											i_field.blur();
											i_cursor.show();

											i_main.focus(true, 10);
										}
									}
									if (i_event.keyCode == Ext.event.Event.LEFT ||
										i_event.keyCode == Ext.event.Event.RIGHT) {

										n_selection = i_event.keyCode == Ext.event.Event.LEFT ? i_inputEl.dom.selectionStart : i_inputEl.dom.selectionEnd;

										i_event.stopEvent();

										if (n_selection === 0 && i_event.keyCode === Ext.event.Event.LEFT) {

											o_position = {
												col: i_field.col,
												lin: i_field.lin
											};

											o_position.col--;

											o_input = {
												x: IceCap.util.Handler.getX(o_position.col),
												y: IceCap.util.Handler.getY(o_position.lin)
											};

											i_self.setCurrentPosition(o_position);

											i_cursor.moveCursor(o_position);

											Ext.apply(o_box, {
												width: i_cursor.getWidth(),
												height: i_cursor.getHeight()
											}, o_input);


											Ext.Array.each(a_inputs, function (i_field) {

												var o_bound = i_field.el.dom.getBoundingClientRect();

												var o_rect = Ext.apply({}, {
													x: IceCap.util.Handler.getX(i_field.col),
													y: IceCap.util.Handler.getY(i_field.lin),
													width: o_bound.width,
													height: o_bound.height
												});

												if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
													b_intersect = true;
													i_field.focus(false, 10);
													return false;
												}
											});

											if (!b_intersect) {

												i_field.blur();
												i_cursor.show();

												i_main.focus(true, 10);
											}
										}
										else if (n_selection == value.length && i_event.keyCode == Ext.event.Event.RIGHT) {

											o_position = {
												col: i_field.col + i_field.maxLength,
												lin: i_field.lin
											};

											if (o_position.col > o_inputData.width) {
												o_position.col = o_inputData.width;
											}

											o_position.col++;

											o_input = {
												x: IceCap.util.Handler.getX(o_position.col),
												y: IceCap.util.Handler.getY(o_position.lin)
											};


											i_self.setCurrentPosition(o_position);
											i_cursor.moveCursor(o_position);

											Ext.apply(o_box, {
												width: i_cursor.getWidth(),
												height: i_cursor.getHeight()
											}, o_input);

											Ext.Array.each(a_inputs, function (i_field) {

												var o_bound = i_field.el.dom.getBoundingClientRect();

												var o_rect = Ext.apply({}, {
													x: IceCap.util.Handler.getX(i_field.col),
													y: IceCap.util.Handler.getY(i_field.lin),
													width: o_bound.width,
													height: o_bound.height
												});

												if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
													b_intersect = true;
													i_field.focus(false, 10);
													return false;
												}
											});

											if (!b_intersect) {

												i_field.blur();
												i_cursor.show();

												i_main.focus(true, 10);
											}
										}
									}
								}
								else {

									if (i_field.xtype == "textarea") {

										if (i_event.keyCode == Ext.event.Event.UP) {

											var s_value = i_field.stripReturns(i_field.getRawValue());

											var regex = new RegExp("^.*\n$|.{1," + o_config.colsize + "}", "gm");

											var a_lines = s_value.match(regex) || [];
											var a_newLines = s_value.split("\n");

											var n_start = i_field.inputEl.dom.selectionStart;

											var n_row = 1;
											var n_char = 0;
											var b_last = i_field.inputEl.dom.selectionStart == i_field.inputEl.dom.value.length;

											Ext.Array.each(a_lines, function (s_part, n_index) {

												n_char += s_part.length;

												if (n_char <= n_start) {
													n_row++;
												}
												else {
													return false;
												}
											});

											if (n_row > 1) {

												i_event.stopEvent();

												n_char = 0;
												var n_left = 0;
												var n_current = 0;
												var n_nextLine = 0;

												n_start = n_start - (a_newLines.length - 1);

												Ext.Array.each(a_lines, function (s_part, n_index) {

													n_char += s_part.length;

													var n_count = 0;

													n_left = 0;

													while (n_count < s_part.length) {
														n_count++;
														if (n_current < n_start) {
															n_current++;
															n_left++;
														}
													}

													if (n_char < n_start) {
														n_row++;
													}
													else {
														n_nextLine = n_index - 1;
														return false;
													}
												});

												if (n_nextLine == -1) {
													n_nextLine = 0;
												}

												var n_newPos = 0;

												Ext.Array.each(a_lines, function (s_part, n_index) {

													if (n_index < n_nextLine) {
														n_newPos += s_part.length;
													}
													else {
														n_newPos += n_left;
														return false;
													}
												});

												i_event.stopEvent();
												i_field.inputEl.dom.setSelectionRange(n_newPos, n_newPos);
											}
										}

										if (i_event.keyCode == Ext.event.Event.DOWN) {

											var s_value = i_field.stripReturns(i_field.getRawValue());
											var n_length = s_value.length;

											var regex = new RegExp("^.*\n$|.{1," + o_config.colsize + "}", "g");
											var n_pos = i_field.inputEl.dom.selectionStart;

											var a_lines = s_value.match(regex) || [];
											var a_newLines = s_value.split("\n");

											if (a_lines.length < o_config.rows && a_newLines.length < o_config.rows) {

												i_event.stopEvent();

												s_value = s_value + "\n";

												i_field.setValue(s_value);

												i_field.inputEl.dom.setSelectionRange(s_value.length, s_value.length);
											}
											else {
												var n_row = 1;
												var n_char = 0;
												var n_left = 0;
												var n_current = 0;
												var n_nextLine = 0;

												Ext.Array.each(a_lines, function (s_part, n_index) {

													n_char += s_part.length;

													var n_count = 0;

													n_left = 0;

													while (n_count < s_part.length) {
														n_count++;
														if (n_current < n_pos) {
															n_current++;
															n_left++;
														}
													}

													if (n_char <= n_pos) {
														n_row++;
													}
													else {
														n_nextLine = n_index + 1;
														return false;
													}
												});

												if (n_nextLine < a_lines.length || n_nextLine < a_newLines.length) {

													var n_newPos = 0;

													Ext.Array.each(a_lines, function (s_part, n_index) {

														if (n_index < n_nextLine) {
															n_newPos += s_part.length;
														}
														else {
															n_newPos += n_left + (a_newLines.length - 1);
															return false;
														}
													});

													if (n_row < o_config.rows) {
														i_event.stopEvent();
														i_field.inputEl.dom.setSelectionRange(n_newPos, n_newPos);
													}
												}
											}

										}
									}
									else if (i_field.xtype == "textfield") {

										var n_typeMode = i_self.getTypeMode();

										if (n_typeMode == IceCap.util.Handler.typeMode.OVERWRITE) {

											var s_direction = i_field.inputEl.el.dom.selectionDirection;

											var n_curpos = s_direction == "forward" ? i_field.inputEl.el.dom.selectionEnd : i_field.inputEl.el.dom.selectionStart;

											var s_key = String.fromCharCode(i_event.keyCode);

											if (n_curpos < value.length && i_regext.test(s_key)) {

												var a_values = value.split("");
												a_values[n_curpos] = i_event.browserEvent.key;
												value = a_values.join("");
												i_field.setValue(value);
												i_field.inputEl.el.dom.selectionEnd = i_field.inputEl.el.dom.selectionStart = n_curpos + 1;
												i_event.stopEvent();
											}
										}
									}
								}
							}
						}
					}
				}, o_meta);

				var o_clone = Ext.clone(o_field);

				if (o_meta.xtype) {

					o_clone.metaField = true;

					o_clone.xtype = s_type = o_meta.xtype;

					delete o_clone.cls;
					delete o_clone.fieldStyle;
					delete o_clone.inputType;
					delete o_clone.ui;
				}

				if (o_config.type == "grid") {

					s_type = "iceCapGrid";

					Ext.apply(o_clone, {
						xtype: s_type,
						gridConfig: o_config.grid,
						width: IceCap.util.Handler.getWidth(n_inputWidth)
					});

					delete o_clone.cls;
					delete o_clone.fieldStyle;
					delete o_clone.inputType;
					delete o_clone.listeners;
					delete o_clone.grid;

					Ext.apply(o_clone, {
						listeners: {
							fieldoption: {
								fn: function (a_config) {
									i_self.fireEvent("fieldoption", a_config);
								}
							},
							key: {
								fn: function (s_key) {
									i_self.fireEvent("key", s_key);
								}
							}
						}
					});
				}

				i_field = Ext.widget(s_type, o_clone);

				var o_on = {};

				Ext.Object.each(o_listeners, function (s_key, value) {

					if (Ext.isFunction(value)) {
						o_on[s_key] = Ext.apply({}, {
							fn: value,
							scope: i_self
						});
					}
					else if (Ext.isObject(value)) {
						value.scope = i_self;
						o_on[s_key] = value;
					}
				});

				i_field.on(o_on);
			}

			if (!i_field.readOnly) {
				n_tabIndex++;
			}

			if (o_config.atr == 25) {

				if (o_field.readOnly) {
					i_field.addCls("icecap-invalid");
				}
				else {
					i_field.markInvalid(true);
				}
			}

			a_fields.push(i_field);
		});

		n_tabIndex = n_tabIndex - 1;
		i_self.setLastTabIndex(n_tabIndex);
		i_self.setCurrentTabIndex(o_inputData.focus);

		i_self.setNeedFocus(n_focus);

		return a_fields;
	},

	createLabels: function () {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_fields = [];
		var a_lines = [];
		var a_temp = [];

		Ext.Array.each(o_inputData.output, function (o_config) {

			var o_line = Ext.Array.findBy(a_lines, function (o_line) {
				return o_line.lin == o_config.lin;
			});

			if (o_line) {
				o_line.items.push(o_config);
			}
			else {
				o_line = {
					items: [o_config],
					lin: o_config.lin,
					col: o_config.col
				};

				a_lines.push(o_line);
			}
		});

		Ext.Array.each(a_lines, function (o_line) {

			var a_items = [];

			Ext.Array.each(o_line.items, function (o_item) {

				var o_atr = Ext.Array.findBy(a_items, function (o_atr) {
					return (o_atr.atr || "") == (o_item.atr || "");
				});

				if (!o_atr) {
					o_atr = {
						lin: o_item.lin,
						items: [o_item],
						atr: o_item.atr || ""
					};

					a_items.push(o_atr);
				}
				else {
					o_atr.items.push(o_item);
				}
			});

			o_line.atr = a_items;
		});

		Ext.Array.each(a_lines, function (o_line) {

			Ext.Array.each(o_line.atr, function (o_atr) {

				var n_col = 0;
				var n_current = 0;
				var s_value = "";

				var o_field = {
					value: ""
				};

				Ext.Array.each(o_atr.items, function (o_config) {

					var s_data = o_config.dta || o_config.label || o_config.text || "";

					if (o_config.off) {
						s_data = Ext.String.leftPad(s_data, s_data.length + o_config.off);
					}

					if (n_col === 0) {

						n_col = o_config.col;
						n_current = n_col + s_data.length;
						s_value = s_data;
					}
					else {

						var n_diff = o_config.col - n_current;

						if (n_diff > 0) {
							s_data = Ext.String.leftPad(s_data, s_data.length + n_diff);
						}

						n_current = n_current + s_data.length;

						s_value = s_value + s_data;
					}
				});

				Ext.apply(o_field, {
					col: n_col,
					lin: o_line.lin,
					value: s_value,
					atr: o_atr.atr
				});

				a_temp.push(o_field);
			});
		});

		Ext.Array.each(a_temp, function (o_config) {

			var s_value = o_config.value;

			if (s_value) {

				var n_x = IceCap.util.Handler.getX(o_config.col);
				var n_y = IceCap.util.Handler.getY(o_config.lin);

				var s_cls = (["iceCap-output-" + (o_config.atr || 20), i_self.getTheme()].filter(Boolean).join("-"));

				var o_field = {
					autoEl: {
						tag: "span"
					},
					html: s_value,
					x: n_x,
					y: n_y,
					cls: ["x-form-display-field-icecap-display", s_cls].join(" "),
					style: {
						"white-space": "pre"
					},
					listeners: {
						afterrender: {
							fn: function (i_field) {
								i_field.el.dom.setAttribute("draggable", false);
							}
						}
					}
				};


				if (o_config.atr == "27") {
					o_field.hidden = true;
				}

				if (o_config.atr == "22") {

					Ext.apply(o_field.style, {
						"font-size": (IceCap.util.Handler.getFontSize() - 1) + "px",
						"font-weight": "bold;",
						"letter-spacing": (IceCap.util.Handler.getColSize() - IceCap.util.Handler.getBoldColSize()) + "px",
						"word-spacing": "0.02em;"
					});
				}

				var i_field = Ext.widget("component", o_field);
				a_fields.push(i_field);
			}
		});

		return a_fields;
	},

	createKeys: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();
		var a_disabledKey = o_inputData.disabledKeys || [];
		var a_buttons = [];

		var i_template = Ext.create("Ext.XTemplate",
			"{id}={text}"
		);

		Ext.Array.each(o_inputData.keys, function(o_config) {

			var s_template = i_template.apply(o_config);

			var o_found = Ext.Array.findBy(a_disabledKey, function(o_disabled) {
				return o_config.id == o_disabled.id;
			});

			o_found = o_found || {
				showKey: 1
			};

			var b_hidden = Number(o_found.showKey) < 1  || false;

			var i_button = Ext.widget("button", {
				text: s_template,
				key: o_config.id,
				focusable: false,
				hidden: b_hidden,
				handler: function(i_button) {
					i_self.doKeyEvent(i_button.key);
				}
			});

			a_buttons.push(i_button);
		});

		return a_buttons;
	},

	createMetaFields: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_fields = [];
		var n_tabIndex = i_self.getLastTabIndex() || 1;

		var a_sliced = Ext.Array.slice(o_inputData.metaFields || []);

		Ext.Array.each(a_sliced, function(o_config) {

			var n_x = o_config.x;
			var n_y = o_config.y;

			if (!o_config.x) {
				n_x = Math.ceil((IceCap.util.Handler.getX(o_config.col) + (IceCap.util.Handler.getColSize() / 2)));
			}

			if (!o_config.y) {
				n_y = IceCap.util.Handler.getY(o_config.lin);
			}

			if (isNaN(n_x)) {
				n_x = IceCap.util.Handler.getColSize();
			}

			if (isNaN(n_y)) {
				n_y = IceCap.util.Handler.getLineHeight();
			}

			var o_listeners = o_config.listeners || {};

			Ext.apply(o_config, {
				tabIndex: n_tabIndex,
				keys: Ext.Array.slice(o_inputData.keys),
				theme: i_self.getTheme(),
				x: n_x,
				y: n_y,
				listeners: {
					fieldoption: {
						fn: function(a_config) {
							i_self.fireEvent("fieldoption", a_config);
						}
					},
					key: {
						fn: function(o_config) {
							i_self.fireEvent("key", o_config);
						}
					}
				}
			});

			n_tabIndex++;

			o_config.xtype = o_config.xtype || o_config.type || "textfield";

			o_config.name = o_config.id;

			delete o_config.id;

			var i_field = Ext.widget(o_config.xtype, o_config);

			var o_on = {};

			Ext.Object.each(o_listeners, function(s_key, value) {

				if (Ext.isFunction(value)) {
					o_on[s_key] = Ext.apply({}, {
						fn: value,
						scope: i_self
					});
				}
				else if (Ext.isObject(value)) {
					value.scope = i_self;
					o_on[s_key] = value;
				}
			});

			i_field.on(o_on);

			a_fields.push(i_field);
		});

		i_self.setLastTabIndex(n_tabIndex);

		return a_fields;
	},

	doCreateFromData: function(o_inputData) {

		var i_self = this;
		i_self.fireEvent("toWindow", i_self, o_inputData);
	},

	recreate: function() {

		var i_self = this;

		var i_content = i_self.getContent();
		var i_keyArea = i_self.getKeyArea();
		var i_main = i_self.getMain();
		var o_inputData = i_self.getInputData();

		var b_fixed = o_inputData.hasOwnProperty("fixed") ? o_inputData.fixed : true;

		IceCap.util.Handler.setFixed(b_fixed);

		i_self.suspendLayouts();

		if (o_inputData.title) {
			i_self.setTitle(o_inputData.title);
		}

		var a_created = i_self.createFields();
		a_created = a_created.concat(i_self.createLabels());
		a_created = a_created.concat(i_self.createMetaFields());
		a_created.push(i_self.createCursor());
		a_created.push(i_self.createMarker());

		i_content.removeAll(true);
		i_keyArea.removeAll(true);

		i_content.add(a_created);

		var a_keys = i_self.createKeys();
		i_keyArea.add(a_keys);

		i_keyArea[a_keys.length === 0 ? "hide" : "show"]();

		var i_marker = i_self.getMarker();
		i_marker.setInUse(i_self.getMarkerActive());

		i_self.updateMessage(o_inputData);


		IceCap.util.Handler.setFixed(true);

		i_self.resumeLayouts(true);

		if (i_content) {
			a_fields = IceCap.util.Handler.getInputFields(i_content);

			var b_found = false;
			var b_error = false;

			if (o_inputData.msgBox && o_inputData.msgBox.text) {
				b_error = true;
			}

			if (a_fields.length > 0) {

				b_found = Ext.Array.findBy(a_fields, function (i_field) {
					return i_field.getTabIndex() === i_self.getNeedFocus();
				});
			}

			if (!b_found) {

				i_self.setCurrentPosition({
					col: o_inputData.csrCol || 1,
					lin: o_inputData.csrLin || 1
				});
			}

			if (b_error) {
				i_self.onError(o_inputData);
			}
			else {
				i_self.findFocus();
			}
		}
	},

	getCurrentField: function() {

		var i_self = this;

		var a_fields = IceCap.util.Handler.getInputFields(i_self);
		var n_tabIndex = i_self.getCurrentTabIndex();
		var i_currentField;

		Ext.Array.each(a_fields, function(i_field) {
			if (i_field.getTabIndex() === n_tabIndex && i_field.hasFocus) {
				i_currentField = i_field;
				return false;
			}
		});

		return i_currentField;
	},

	doKeyEvent: function(s_value, i_event) {

		if (i_event) {
			i_event.stopEvent();
		}

		var i_self = this;

		var i_controller = i_self.getController();

		var o_inputData = i_self.getInputData() || {};

		var a_disabledKeys = Ext.Array.from(o_inputData.disabledKeys || []);

		var o_found = Ext.Array.findBy(a_disabledKeys, function (o_key) {
			return s_value == o_key.id;
		});

		if (!o_found) {
			i_controller.doKeyEvent(s_value);
		}
		else {

			Ext.Msg.show({
				title: "Error",
				msg: "Funktionstasten er ikke tilladt",
				icon: Ext.MessageBox.INFO,
				buttons: Ext.MessageBox.OK,
				fn: function () {
					i_self.findFocus();
				}
			});
		}
	},

	doNavigationKey: function(n_direction, b_tab, i_event) {

		if (i_event) {
			i_event.stopPropagation();
			i_event.preventDefault();
		}

		var i_self = this;
		var i_controller = i_self.getController();
		i_controller[b_tab ? "doTabKey" : "doArrowKeys"](n_direction);
	},

	addKeyEvents: function() {

		var i_self = this;

		var a_bindings = [
			{
				key: Ext.event.Event.PAGE_DOWN,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ROLLUP", i_event);
				}
			},
			{
				key: Ext.event.Event.PAGE_UP,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ROLLDOWN", i_event);
				}
			},
			{
				key: Ext.event.Event.ENTER,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ENTER", i_event);
				}
			},
			{
				key: Ext.event.Event.ESC,
				fn: function(n_key, i_event) {

					i_event.preventDefault();

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ATTN", i_event);
				}
			},
			{
				key: Ext.event.Event.UP,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_activeComponent = Ext.ComponentManager.getActiveComponent();
					var i_content = i_self.getContent();

					if (i_content.contains(i_activeComponent) || i_content.ownerCt == i_activeComponent) {

						if (!i_event.target.type) {

							i_event.stopEvent();

							var i_cursor = i_self.getCursor();
							var o_position = i_self.getCurrentPosition();

							var a_inputs = IceCap.util.Handler.getInputFields(i_self);

							o_position.lin--;

							if (o_position.lin < 1) {
								o_position.lin = 1;
							}

							var o_box = Ext.apply({
								x: IceCap.util.Handler.getX(o_position.col),
								y: IceCap.util.Handler.getY(o_position.lin),
								width: i_cursor.getWidth(),
								height: i_cursor.getHeight()
							});

							var b_intersect = false;

							Ext.Array.each(a_inputs, function(i_field) {

								var o_bound = i_field.el.dom.getBoundingClientRect();

								var o_rect = Ext.apply({}, {
									x: IceCap.util.Handler.getX(i_field.col),
									y: IceCap.util.Handler.getY(i_field.lin),
									width: o_bound.width,
									height: o_bound.height
								});

								if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
									b_intersect = true;
									i_field.focus(false, 10);


									var n_start = o_position.col - i_field.col;
									var i_inputEl = i_field.inputEl;
									i_inputEl.dom.selectionStart = i_inputEl.dom.selectionEnd = n_start;

									return false;
								}
							});

							if (!b_intersect) {

								i_cursor.moveCursor(o_position);
							}
							i_self.setCurrentPosition(o_position);
						}
						else {
							i_self.doNavigationKey(0, false, i_event);
						}
					}
				}
			},
			{
				key: Ext.event.Event.DOWN,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_activeComponent = Ext.ComponentManager.getActiveComponent();
					var i_content = i_self.getContent();

					if (i_content.contains(i_activeComponent) || i_content.ownerCt == i_activeComponent) {

						if (!i_event.target.type) {

							i_event.stopEvent();

							var i_cursor = i_self.getCursor();
							var o_position = i_self.getCurrentPosition();
							var o_inputData = i_self.getInputData();
							var o_window = o_inputData.window;

							var a_inputs = IceCap.util.Handler.getInputFields(i_self);

							o_position.lin++;

							if (o_position.lin > o_window.height) {
								o_position.lin = o_window.height;
							}

							var o_box = Ext.apply({
								x: IceCap.util.Handler.getX(o_position.col),
								y: IceCap.util.Handler.getY(o_position.lin),
								width: i_cursor.getWidth(),
								height: i_cursor.getHeight()
							});

							var b_intersect = false;

							Ext.Array.each(a_inputs, function(i_field) {

								var o_bound = i_field.el.dom.getBoundingClientRect();

								var o_rect = Ext.apply({}, {
									x: IceCap.util.Handler.getX(i_field.col),
									y: IceCap.util.Handler.getY(i_field.lin),
									width: o_bound.width,
									height: o_bound.height
								});

								if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
									b_intersect = true;
									i_field.focus(false, 10);

									var n_start = o_position.col -i_field.col;
									var i_inputEl = i_field.inputEl;
									i_inputEl.dom.selectionStart = i_inputEl.dom.selectionEnd = n_start;

									return false;
								}
							});

							if (!b_intersect) {

								i_cursor.moveCursor(o_position);
							}
							i_self.setCurrentPosition(o_position);
						}
						else {
							i_self.doNavigationKey(1, false, i_event);
						}
					}
				}
			},
			{
				key: Ext.event.Event.LEFT,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_activeComponent = Ext.ComponentManager.getActiveComponent();
					var i_content = i_self.getContent();

					if (i_content.contains(i_activeComponent) || i_content.ownerCt == i_activeComponent) {

						if (!i_event.target.type) {
							i_event.stopEvent();

							var i_cursor = i_self.getCursor();
							var o_position = i_self.getCurrentPosition();

							var a_inputs = IceCap.util.Handler.getInputFields(i_self);

							o_position.col--;

							if (o_position.col < 1) {
								o_position.col = 1;
							}

							var o_box = Ext.apply({
								x: IceCap.util.Handler.getX(o_position.col),
								y: IceCap.util.Handler.getY(o_position.lin),
								width: i_cursor.getWidth(),
								height: i_cursor.getHeight()
							});

							var b_intersect = false;

							Ext.Array.each(a_inputs, function(i_field) {

								var o_bound = i_field.el.dom.getBoundingClientRect();

								var o_rect = Ext.apply({}, {
									x: IceCap.util.Handler.getX(i_field.col),
									y: IceCap.util.Handler.getY(i_field.lin),
									width: o_bound.width,
									height: o_bound.height
								});

								if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
									b_intersect = true;
									i_field.focus(false, 10);
									return false;
								}
							});

							if (!b_intersect) {

								i_cursor.moveCursor(o_position);
							}

							i_self.setCurrentPosition(o_position);
						}
					}
				}
			},
			{
				key: Ext.event.Event.RIGHT,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_activeComponent = Ext.ComponentManager.getActiveComponent();
					var i_content = i_self.getContent();

					if (i_content.contains(i_activeComponent) || i_content.ownerCt == i_activeComponent) {

						if (!i_event.target.type) {

							i_event.stopEvent();

							var i_cursor = i_self.getCursor();
							var o_position = i_self.getCurrentPosition();
							var o_inputData = i_self.getInputData();

							var a_inputs = IceCap.util.Handler.getInputFields(i_self);

							o_position.col++;

							if (o_position.col > o_inputData.width) {
								o_position.col = o_inputData.width;
							}

							var o_box = Ext.apply({
								x: IceCap.util.Handler.getX(o_position.col),
								y: IceCap.util.Handler.getY(o_position.lin),
								width: i_cursor.getWidth(),
								height: i_cursor.getHeight()
							});

							var b_intersect = false;

							Ext.Array.each(a_inputs, function(i_field) {

								var o_bound = i_field.el.dom.getBoundingClientRect();

								var o_rect = Ext.apply({}, {
									x: IceCap.util.Handler.getX(i_field.col),
									y: IceCap.util.Handler.getY(i_field.lin),
									width: o_bound.width,
									height: o_bound.height
								});

								if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
									b_intersect = true;
									i_field.focus(false, 10);
									return false;
								}
							});

							if (!b_intersect) {

								i_cursor.moveCursor(o_position);
							}

							i_self.setCurrentPosition(o_position);
						}
					}
				}
			},
			{
				key: Ext.event.Event.TAB,
				shift: false,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_activeComponent = Ext.ComponentManager.getActiveComponent();
					var i_content = i_self.getContent();

					if (i_content.contains(i_activeComponent) || i_content.ownerCt == i_activeComponent) {

						i_self.doNavigationKey(1, true, i_event);
					}
				}
			},
			{
				key: Ext.event.Event.TAB,
				shift: true,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_activeComponent = Ext.ComponentManager.getActiveComponent();
					var i_content = i_self.getContent();

					if (i_content.contains(i_activeComponent) || i_content.ownerCt == i_activeComponent) {

						i_self.doNavigationKey(0, true, i_event);
					}
				}
			},
			{
				key: Ext.event.Event.NUM_PLUS,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					var i_field = i_self.getCurrentField();

					if (i_field) {

						var n_start = i_field.inputEl.el.dom.selectionStart;

						var s_text = i_field.getValue();

						s_text = s_text.substr(0, n_start);

						i_field.setValue(s_text);

						i_self.doNavigationKey(1, true, i_event);
					}
				}
			},
			{
				key: Ext.event.Event.HOME,
				ctrl: true,
				alt: false,
				fn: function(n_key, i_event) {

					i_event.stopEvent();

					var i_key = this;
					var i_self = i_key.target.component;

					var b_markerActive = i_self.getMarkerActive();
					var i_marker = i_self.getMarker();

					i_self.setMarkerActive(!b_markerActive);

					i_marker.toggle();
				}
			},
			{
				key: Ext.event.Event.INSERT,
				ctrl: false,
				alt: false,
				fn: function (n_key, i_event) {

					var n_type = i_self.getTypeMode();
					switch (n_type) {
						case IceCap.util.Handler.typeMode.OVERWRITE:
							n_type = IceCap.util.Handler.typeMode.INSERT;
							break;
						default:
							n_type = IceCap.util.Handler.typeMode.OVERWRITE;
							break;
					}

					i_self.setTypeMode(n_type);
				}
			}
		];

		a_bindings = a_bindings.concat(i_self.getFKeys());

		var i_keyMap = Ext.create("Ext.util.KeyMap", {
			target: i_self.getEl(),
			binding: a_bindings
		});
	},

	getFKeys: function() {

		var i_self = this;

		var a_keys = [
			{
				key: Ext.event.Event.F1,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F1", i_event);
				}
			},
			{
				key: Ext.event.Event.F2,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F2", i_event);
				}
			},
			{
				key: Ext.event.Event.F3,
				shift: false,
				alt: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F3", i_event);
				}
			},
			{
				key: Ext.event.Event.F4,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F4", i_event);
				}
			},
			{
				key: Ext.event.Event.F5,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F5", i_event);
				}
			},
			{
				key: Ext.event.Event.F6,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F6", i_event);
				}
			},
			{
				key: Ext.event.Event.F7,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F7", i_event);
				}
			},
			{
				key: Ext.event.Event.F8,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F8", i_event);
				}
			},
			{
				key: Ext.event.Event.F9,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F9", i_event);
				}
			},
			{
				key: Ext.event.Event.F10,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F10", i_event);
				}
			},
			{
				key: Ext.event.Event.F11,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F11", i_event);
				}
			},
			{
				key: Ext.event.Event.F12,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F12", i_event);
				}
			}
		];

		a_keys = a_keys.concat(i_self.getFShiftKeys());

		return a_keys;
	},

	getFShiftKeys: function() {

		var i_self = this;

		var a_keys = [
			{
				key: Ext.event.Event.F1,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F13", i_event);
				}
			},
			{
				key: Ext.event.Event.F2,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F14", i_event);
				}
			},
			{
				key: Ext.event.Event.F3,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F15", i_event);
				}
			},
			{
				key: Ext.event.Event.F4,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F16", i_event);
				}
			},
			{
				key: Ext.event.Event.F5,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F17", i_event);
				}
			},
			{
				key: Ext.event.Event.F6,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F18", i_event);
				}
			},
			{
				key: Ext.event.Event.F7,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F19", i_event);
				}
			},
			{
				key: Ext.event.Event.F8,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F20", i_event);
				}
			},
			{
				key: Ext.event.Event.F9,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F21", i_event);
				}
			},
			{
				key: Ext.event.Event.F10,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F22", i_event);
				}
			},
			{
				key: Ext.event.Event.F11,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F23", i_event);
				}
			},
			{
				key: Ext.event.Event.F12,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F24", i_event);
				}
			}
		];

		return a_keys;
	},

	createCursor: function () {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var i_cursor = Ext.widget("icecap-cursor", {
			theme: i_self.getTheme(),
			width: IceCap.util.Handler.getWidth(),
			listeners: {
				show: {
					fn: function (i_cursor) {

						var i_marker = i_self.getMarker();
						var b_active = i_marker.getInUse();

						if (b_active) {
							i_marker.show();
						}
					}
				},
				render: {
					fn: function (i_item) {
						i_item.hide();
					}
				},
				afterrender: {
					fn: function (i_cursor) {

						var i_content = i_self.getContent();

						var a_fields = IceCap.util.Handler.getInputFields(i_content);

						if (a_fields.length === 0) {

							i_cursor.show();

							i_cursor.moveCursor({
								col: o_inputData.csrCol || 1,
								lin: o_inputData.csrLin || 1
							});
						}
					}
				}
			},
			moveCursor: function (o_position) {

				var i_cursor = this;
				var i_marker = i_self.getMarker();

				var n_x = IceCap.util.Handler.getX(o_position.col);
				var n_y = IceCap.util.Handler.getY(o_position.lin + 1);

				var a_pos = [
					n_x,
					n_y
				];

				i_cursor.move([
					n_x,
					n_y - 11
				]);
				i_marker.move([
					n_x - 7,
					n_y - 12
				]);

				i_self.updateCurrentPosition(o_position);
			}
		});

		i_self.setCursor(i_cursor);

		return i_cursor;
	},

	createMarker: function() {

		var i_self = this;

		var i_marker = Ext.widget("icecap-marker", {
			hidden: true,
			active: false,
			inUse: false,
			ui: i_self.getTheme() || "default"
		});

		i_self.setMarker(i_marker);

		return i_marker;
	},

	findFocus: function() {

		var i_self = this;
		var i_main = i_self.getMain();
		var i_content = i_self.getContent();

		var a_fields = IceCap.util.Handler.getInputFields(i_content);

		if (a_fields.length > 0) {

			var i_field = a_fields[0];
			i_field.focus(false, 10);
		}
		else {
			i_main.focus(false, 10);
		}
	},

	doTimer: function() {

		var i_self = this;

		var i_timer = i_self.getTimer();
		if (!i_timer) {
			i_timer = new Ext.util.DelayedTask(function() {
				i_self.setLoading(true);
			});

			i_self.setTimer(i_timer);

			i_timer.delay(1000);
		}
	},

	cancelTimer: function() {

		var i_self = this;

		var i_timer = i_self.getTimer();

		if (i_timer) {
			i_timer.cancel();
			i_self.setTimer(null);
		}
	},

	onError: function(o_inputData) {

		var i_self = this;

		Ext.Msg.show({
			title: "Server Message",
			msg: o_inputData.msgBox.text,
			icon: Ext.MessageBox.INFO,
			buttons: Ext.MessageBox.OK,
			fn: function(btn) {
				i_self.findFocus();
			}
		});
	},

	updateMessage: function (o_inputData) {

		var i_self = this;
		var i_statusbar = i_self.getStatusBar();

		var a_messages = Ext.Array.from(o_inputData.message);

		var a_result = [];

		if (a_messages.length > 1) {

			a_result.push(a_messages[0].text);
		}
		else {
			Ext.Array.each(a_messages, function(o_message) {
				a_result.push(o_message.text);
			});
		}

		var i_messageLabel = i_statusbar.getComponent("icecap-message");

		var s_message = a_result.join(" ");

		if (Ext.String.startsWith(s_message.toLowerCase(), "(c)")) {
			i_messageLabel.removeCls("icecap-statusbar-error");

		}
		else {
			i_messageLabel.addCls("icecap-statusbar-error")
		}
		i_messageLabel.setText(s_message);
	},

	applyFFW: function (o_config) {

		var i_self = this;
		var s_hex = o_config.ffw;
		var b_fixed = IceCap.util.Handler.getFixed();

		var o_field = {
			xtype: "textfield"
		};

		var o_fieldStyle = {
		};

		if (o_config.ta) {

			Ext.apply(o_fieldStyle, {
				"text-align": o_config.ta
			});
		}

		if (s_hex) {

			var n_hex = parseInt(s_hex);

			var n_sanHex = IceCap.util.Handler.createIndicators(s_hex);

			if (n_sanHex & IceCap.util.Handler.FFW.BYPASS) {

				Ext.apply(o_field, {
					readOnly: true
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.ALPHA_ONLY) {

				Ext.apply(o_field, {
					maskRe: new RegExp("[a-z A-Z ,.-]")
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.NUMERIC_ONLY) {

				Ext.apply(o_field, {
					maskRe: new RegExp("[+\\-,. 0-9]")
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.DIGITS_ONLY) {

				Ext.apply(o_field, {
					maskRe: new RegExp("[0-9]")
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.MOD_DATA) {

				Ext.apply(o_field, {
					listeners: {
						afterrender: {
							fn: function (i_field) {

								i_field.originalValue = 0xFF;
							},
							single: true
						}
					}
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.AUTO_ENTER) {

				// THIS WE DONT NEED IN THE MODERN WORLD...

				// Ext.apply(o_field, {
				// 	listeners: {
				// 		blur: {
				// 			fn: function(i_field) {
				// 				i_self.doKeyEvent("ENTER");
				// 			}
				// 		}
				// 	}
				// });
			}

			if (n_sanHex & IceCap.util.Handler.FFW.MONOCASE) {

				// Ext.apply(o_fieldStyle, {
				// 	"text-transform": "uppercase"
				// });
			}

			if (n_sanHex & IceCap.util.Handler.FFW.MAND_ENTER) {

				Ext.apply(o_field, {
					allowBlank: false
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.RA_ZEROFILL ||
				n_sanHex & IceCap.util.Handler.FFW.RA_BLANKFILL ||
				n_sanHex & IceCap.util.Handler.FFW.RA_MANDATORY) {

				Ext.apply(o_fieldStyle, {
					"text-align": "right"
				});
			}

			if (o_config.atr == "27" && n_hex & (1 << 13)) {

				Ext.apply(o_field, {
					hidden: true,
					disabled: true
				});
			}
		}

		Ext.apply(o_field, {
			fieldStyle: o_fieldStyle
		});

		return o_field;
	},

	updateCurrentPosition: function (o_position) {

		var i_self = this;
		var i_statusbar = i_self.getStatusBar();

		if (i_statusbar) {
			var i_position = i_statusbar.getComponent("icecap-position");

			if (i_position) {

				var a_result = [
					o_position.lin,
					o_position.col
				];

				i_position.setText(a_result.join("/"));
			}

			i_self.updateTypeMode(i_self.getTypeMode())
		}
	},

	updateTypeMode: function (n_type) {

		var i_self = this;

		var i_statusbar = i_self.getStatusBar();

		if (i_statusbar) {

			var i_typeLabel = i_statusbar.getComponent("icecap-typemode");

			var a_mode = [
			];

			if (i_typeLabel) {

				switch (n_type) {
					case IceCap.util.Handler.typeMode.OVERWRITE:
						a_mode.push(" DEL");
						break;

					default:
						a_mode.push(" INS");
						break;
				}

				i_typeLabel.setText(a_mode.join(" "));
			}
		}
	}
});
