michael@0: // -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString; michael@0: const nsISupportsString = Components.interfaces.nsISupportsString; michael@0: const nsIPrefBranch = Components.interfaces.nsIPrefBranch; michael@0: const nsIClipboardHelper = Components.interfaces.nsIClipboardHelper; michael@0: const nsIAtomService = Components.interfaces.nsIAtomService; michael@0: michael@0: const nsSupportsString_CONTRACTID = "@mozilla.org/supports-string;1"; michael@0: const nsPrompt_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1"; michael@0: const nsPrefService_CONTRACTID = "@mozilla.org/preferences-service;1"; michael@0: const nsClipboardHelper_CONTRACTID = "@mozilla.org/widget/clipboardhelper;1"; michael@0: const nsAtomService_CONTRACTID = "@mozilla.org/atom-service;1"; michael@0: michael@0: const gPrefBranch = Services.prefs; michael@0: const gClipboardHelper = Components.classes[nsClipboardHelper_CONTRACTID].getService(nsIClipboardHelper); michael@0: const gAtomService = Components.classes[nsAtomService_CONTRACTID].getService(nsIAtomService); michael@0: michael@0: var gLockProps = ["default", "user", "locked"]; michael@0: // we get these from a string bundle michael@0: var gLockStrs = []; michael@0: var gTypeStrs = []; michael@0: michael@0: const PREF_IS_DEFAULT_VALUE = 0; michael@0: const PREF_IS_USER_SET = 1; michael@0: const PREF_IS_LOCKED = 2; michael@0: michael@0: var gPrefHash = {}; michael@0: var gPrefArray = []; michael@0: var gPrefView = gPrefArray; // share the JS array michael@0: var gSortedColumn = "prefCol"; michael@0: var gSortFunction = null; michael@0: var gSortDirection = 1; // 1 is ascending; -1 is descending michael@0: var gConfigBundle = null; michael@0: var gFilter = null; michael@0: michael@0: var view = { michael@0: get rowCount() { return gPrefView.length; }, michael@0: getCellText : function(index, col) { michael@0: if (!(index in gPrefView)) michael@0: return ""; michael@0: michael@0: var value = gPrefView[index][col.id]; michael@0: michael@0: switch (col.id) { michael@0: case "lockCol": michael@0: return gLockStrs[value]; michael@0: case "typeCol": michael@0: return gTypeStrs[value]; michael@0: default: michael@0: return value; michael@0: } michael@0: }, michael@0: getRowProperties : function(index) { return ""; }, michael@0: getCellProperties : function(index, col) { michael@0: if (index in gPrefView) michael@0: return gLockProps[gPrefView[index].lockCol]; michael@0: michael@0: return ""; michael@0: }, michael@0: getColumnProperties : function(col) { return ""; }, michael@0: treebox : null, michael@0: selection : null, michael@0: isContainer : function(index) { return false; }, michael@0: isContainerOpen : function(index) { return false; }, michael@0: isContainerEmpty : function(index) { return false; }, michael@0: isSorted : function() { return true; }, michael@0: canDrop : function(index, orientation) { return false; }, michael@0: drop : function(row, orientation) {}, michael@0: setTree : function(out) { this.treebox = out; }, michael@0: getParentIndex: function(rowIndex) { return -1; }, michael@0: hasNextSibling: function(rowIndex, afterIndex) { return false; }, michael@0: getLevel: function(index) { return 1; }, michael@0: getImageSrc: function(row, col) { return ""; }, michael@0: toggleOpenState : function(index) {}, michael@0: cycleHeader: function(col) { michael@0: var index = this.selection.currentIndex; michael@0: if (col.id == gSortedColumn) { michael@0: gSortDirection = -gSortDirection; michael@0: gPrefArray.reverse(); michael@0: if (gPrefView != gPrefArray) michael@0: gPrefView.reverse(); michael@0: if (index >= 0) michael@0: index = gPrefView.length - index - 1; michael@0: } michael@0: else { michael@0: var pref = null; michael@0: if (index >= 0) michael@0: pref = gPrefView[index]; michael@0: michael@0: var old = document.getElementById(gSortedColumn); michael@0: old.setAttribute("sortDirection", ""); michael@0: gPrefArray.sort(gSortFunction = gSortFunctions[col.id]); michael@0: if (gPrefView != gPrefArray) michael@0: gPrefView.sort(gSortFunction); michael@0: gSortedColumn = col.id; michael@0: if (pref) michael@0: index = getViewIndexOfPref(pref); michael@0: } michael@0: col.element.setAttribute("sortDirection", gSortDirection > 0 ? "ascending" : "descending"); michael@0: this.treebox.invalidate(); michael@0: if (index >= 0) { michael@0: this.selection.select(index); michael@0: this.treebox.ensureRowIsVisible(index); michael@0: } michael@0: }, michael@0: selectionChanged : function() {}, michael@0: cycleCell: function(row, col) {}, michael@0: isEditable: function(row, col) {return false; }, michael@0: isSelectable: function(row, col) {return false; }, michael@0: setCellValue: function(row, col, value) {}, michael@0: setCellText: function(row, col, value) {}, michael@0: performAction: function(action) {}, michael@0: performActionOnRow: function(action, row) {}, michael@0: performActionOnCell: function(action, row, col) {}, michael@0: isSeparator: function(index) {return false; } michael@0: }; michael@0: michael@0: // find the index in gPrefView of a pref object michael@0: // or -1 if it does not exist in the filtered view michael@0: function getViewIndexOfPref(pref) michael@0: { michael@0: var low = -1, high = gPrefView.length; michael@0: var index = (low + high) >> 1; michael@0: while (index > low) { michael@0: var mid = gPrefView[index]; michael@0: if (mid == pref) michael@0: return index; michael@0: if (gSortFunction(mid, pref) < 0) michael@0: low = index; michael@0: else michael@0: high = index; michael@0: index = (low + high) >> 1; michael@0: } michael@0: return -1; michael@0: } michael@0: michael@0: // find the index in gPrefView where a pref object belongs michael@0: function getNearestViewIndexOfPref(pref) michael@0: { michael@0: var low = -1, high = gPrefView.length; michael@0: var index = (low + high) >> 1; michael@0: while (index > low) { michael@0: if (gSortFunction(gPrefView[index], pref) < 0) michael@0: low = index; michael@0: else michael@0: high = index; michael@0: index = (low + high) >> 1; michael@0: } michael@0: return high; michael@0: } michael@0: michael@0: // find the index in gPrefArray of a pref object michael@0: function getIndexOfPref(pref) michael@0: { michael@0: var low = -1, high = gPrefArray.length; michael@0: var index = (low + high) >> 1; michael@0: while (index > low) { michael@0: var mid = gPrefArray[index]; michael@0: if (mid == pref) michael@0: return index; michael@0: if (gSortFunction(mid, pref) < 0) michael@0: low = index; michael@0: else michael@0: high = index; michael@0: index = (low + high) >> 1; michael@0: } michael@0: return index; michael@0: } michael@0: michael@0: function getNearestIndexOfPref(pref) michael@0: { michael@0: var low = -1, high = gPrefArray.length; michael@0: var index = (low + high) >> 1; michael@0: while (index > low) { michael@0: if (gSortFunction(gPrefArray[index], pref) < 0) michael@0: low = index; michael@0: else michael@0: high = index; michael@0: index = (low + high) >> 1; michael@0: } michael@0: return high; michael@0: } michael@0: michael@0: var gPrefListener = michael@0: { michael@0: observe: function(subject, topic, prefName) michael@0: { michael@0: if (topic != "nsPref:changed") michael@0: return; michael@0: michael@0: var arrayIndex = gPrefArray.length; michael@0: var viewIndex = arrayIndex; michael@0: var selectedIndex = view.selection.currentIndex; michael@0: var pref; michael@0: var updateView = false; michael@0: var updateArray = false; michael@0: var addedRow = false; michael@0: if (prefName in gPrefHash) { michael@0: pref = gPrefHash[prefName]; michael@0: viewIndex = getViewIndexOfPref(pref); michael@0: arrayIndex = getIndexOfPref(pref); michael@0: fetchPref(prefName, arrayIndex); michael@0: // fetchPref replaces the existing pref object michael@0: pref = gPrefHash[prefName]; michael@0: if (viewIndex >= 0) { michael@0: // Might need to update the filtered view michael@0: gPrefView[viewIndex] = gPrefHash[prefName]; michael@0: view.treebox.invalidateRow(viewIndex); michael@0: } michael@0: if (gSortedColumn == "lockCol" || gSortedColumn == "valueCol") { michael@0: updateArray = true; michael@0: gPrefArray.splice(arrayIndex, 1); michael@0: if (gFilter && gFilter.test(pref.prefCol + ";" + pref.valueCol)) { michael@0: updateView = true; michael@0: gPrefView.splice(viewIndex, 1); michael@0: } michael@0: } michael@0: } michael@0: else { michael@0: fetchPref(prefName, arrayIndex); michael@0: pref = gPrefArray.pop(); michael@0: updateArray = true; michael@0: addedRow = true; michael@0: if (gFilter && gFilter.test(pref.prefCol + ";" + pref.valueCol)) { michael@0: updateView = true; michael@0: } michael@0: } michael@0: if (updateArray) { michael@0: // Reinsert in the data array michael@0: var newIndex = getNearestIndexOfPref(pref); michael@0: gPrefArray.splice(newIndex, 0, pref); michael@0: michael@0: if (updateView) { michael@0: // View is filtered, reinsert in the view separately michael@0: newIndex = getNearestViewIndexOfPref(pref); michael@0: gPrefView.splice(newIndex, 0, pref); michael@0: } michael@0: else if (gFilter) { michael@0: // View is filtered, but nothing to update michael@0: return; michael@0: } michael@0: michael@0: if (addedRow) michael@0: view.treebox.rowCountChanged(newIndex, 1); michael@0: michael@0: // Invalidate the changed range in the view michael@0: var low = Math.min(viewIndex, newIndex); michael@0: var high = Math.max(viewIndex, newIndex); michael@0: view.treebox.invalidateRange(low, high); michael@0: michael@0: if (selectedIndex == viewIndex) { michael@0: selectedIndex = newIndex; michael@0: } michael@0: else if (selectedIndex >= low && selectedIndex <= high) { michael@0: selectedIndex += (newIndex > viewIndex) ? -1 : 1; michael@0: } michael@0: if (selectedIndex >= 0) { michael@0: view.selection.select(selectedIndex); michael@0: if (selectedIndex == newIndex) michael@0: view.treebox.ensureRowIsVisible(selectedIndex); michael@0: } michael@0: } michael@0: } michael@0: }; michael@0: michael@0: function prefObject(prefName, prefIndex) michael@0: { michael@0: this.prefCol = prefName; michael@0: } michael@0: michael@0: prefObject.prototype = michael@0: { michael@0: lockCol: PREF_IS_DEFAULT_VALUE, michael@0: typeCol: nsIPrefBranch.PREF_STRING, michael@0: valueCol: "" michael@0: }; michael@0: michael@0: function fetchPref(prefName, prefIndex) michael@0: { michael@0: var pref = new prefObject(prefName); michael@0: michael@0: gPrefHash[prefName] = pref; michael@0: gPrefArray[prefIndex] = pref; michael@0: michael@0: if (gPrefBranch.prefIsLocked(prefName)) michael@0: pref.lockCol = PREF_IS_LOCKED; michael@0: else if (gPrefBranch.prefHasUserValue(prefName)) michael@0: pref.lockCol = PREF_IS_USER_SET; michael@0: michael@0: try { michael@0: switch (gPrefBranch.getPrefType(prefName)) { michael@0: case gPrefBranch.PREF_BOOL: michael@0: pref.typeCol = gPrefBranch.PREF_BOOL; michael@0: // convert to a string michael@0: pref.valueCol = gPrefBranch.getBoolPref(prefName).toString(); michael@0: break; michael@0: case gPrefBranch.PREF_INT: michael@0: pref.typeCol = gPrefBranch.PREF_INT; michael@0: // convert to a string michael@0: pref.valueCol = gPrefBranch.getIntPref(prefName).toString(); michael@0: break; michael@0: default: michael@0: case gPrefBranch.PREF_STRING: michael@0: pref.valueCol = gPrefBranch.getComplexValue(prefName, nsISupportsString).data; michael@0: // Try in case it's a localized string (will throw an exception if not) michael@0: if (pref.lockCol == PREF_IS_DEFAULT_VALUE && michael@0: /^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.valueCol)) michael@0: pref.valueCol = gPrefBranch.getComplexValue(prefName, nsIPrefLocalizedString).data; michael@0: break; michael@0: } michael@0: } catch (e) { michael@0: // Also catch obscure cases in which you can't tell in advance michael@0: // that the pref exists but has no user or default value... michael@0: } michael@0: } michael@0: michael@0: function onConfigLoad() michael@0: { michael@0: // Load strings michael@0: gConfigBundle = document.getElementById("configBundle"); michael@0: michael@0: gLockStrs[PREF_IS_DEFAULT_VALUE] = gConfigBundle.getString("default"); michael@0: gLockStrs[PREF_IS_USER_SET] = gConfigBundle.getString("user"); michael@0: gLockStrs[PREF_IS_LOCKED] = gConfigBundle.getString("locked"); michael@0: michael@0: gTypeStrs[nsIPrefBranch.PREF_STRING] = gConfigBundle.getString("string"); michael@0: gTypeStrs[nsIPrefBranch.PREF_INT] = gConfigBundle.getString("int"); michael@0: gTypeStrs[nsIPrefBranch.PREF_BOOL] = gConfigBundle.getString("bool"); michael@0: michael@0: var showWarning = gPrefBranch.getBoolPref("general.warnOnAboutConfig"); michael@0: michael@0: if (showWarning) michael@0: document.getElementById("warningButton").focus(); michael@0: else michael@0: ShowPrefs(); michael@0: } michael@0: michael@0: // Unhide the warning message michael@0: function ShowPrefs() michael@0: { michael@0: gPrefBranch.getChildList("").forEach(fetchPref); michael@0: michael@0: var descending = document.getElementsByAttribute("sortDirection", "descending"); michael@0: if (descending.item(0)) { michael@0: gSortedColumn = descending[0].id; michael@0: gSortDirection = -1; michael@0: } michael@0: else { michael@0: var ascending = document.getElementsByAttribute("sortDirection", "ascending"); michael@0: if (ascending.item(0)) michael@0: gSortedColumn = ascending[0].id; michael@0: else michael@0: document.getElementById(gSortedColumn).setAttribute("sortDirection", "ascending"); michael@0: } michael@0: gSortFunction = gSortFunctions[gSortedColumn]; michael@0: gPrefArray.sort(gSortFunction); michael@0: michael@0: gPrefBranch.addObserver("", gPrefListener, false); michael@0: michael@0: var configTree = document.getElementById("configTree"); michael@0: configTree.view = view; michael@0: configTree.controllers.insertControllerAt(0, configController); michael@0: michael@0: document.getElementById("configDeck").setAttribute("selectedIndex", 1); michael@0: document.getElementById("configTreeKeyset").removeAttribute("disabled"); michael@0: if (!document.getElementById("showWarningNextTime").checked) michael@0: gPrefBranch.setBoolPref("general.warnOnAboutConfig", false); michael@0: michael@0: // Process about:config?filter= michael@0: var textbox = document.getElementById("textbox"); michael@0: // About URIs don't support query params, so do this manually michael@0: var loc = document.location.href; michael@0: var matches = /[?&]filter\=([^&]+)/i.exec(loc); michael@0: if (matches) michael@0: textbox.value = decodeURIComponent(matches[1]); michael@0: michael@0: // Even if we did not set the filter string via the URL query, michael@0: // textbox might have been set via some other mechanism michael@0: if (textbox.value) michael@0: FilterPrefs(); michael@0: textbox.focus(); michael@0: } michael@0: michael@0: function onConfigUnload() michael@0: { michael@0: if (document.getElementById("configDeck").getAttribute("selectedIndex") == 1) { michael@0: gPrefBranch.removeObserver("", gPrefListener); michael@0: var configTree = document.getElementById("configTree"); michael@0: configTree.view = null; michael@0: configTree.controllers.removeController(configController); michael@0: } michael@0: } michael@0: michael@0: function FilterPrefs() michael@0: { michael@0: if (document.getElementById("configDeck").getAttribute("selectedIndex") != 1) { michael@0: return; michael@0: } michael@0: michael@0: var substring = document.getElementById("textbox").value; michael@0: // Check for "/regex/[i]" michael@0: if (substring.charAt(0) == '/') { michael@0: var r = substring.match(/^\/(.*)\/(i?)$/); michael@0: try { michael@0: gFilter = RegExp(r[1], r[2]); michael@0: } michael@0: catch (e) { michael@0: return; // Do nothing on incomplete or bad RegExp michael@0: } michael@0: } michael@0: else if (substring) { michael@0: gFilter = RegExp(substring.replace(/([^* \w])/g, "\\$1") michael@0: .replace(/^\*+/, "").replace(/\*+/g, ".*"), "i"); michael@0: } else { michael@0: gFilter = null; michael@0: } michael@0: michael@0: var prefCol = (view.selection && view.selection.currentIndex < 0) ? michael@0: null : gPrefView[view.selection.currentIndex].prefCol; michael@0: var oldlen = gPrefView.length; michael@0: gPrefView = gPrefArray; michael@0: if (gFilter) { michael@0: gPrefView = []; michael@0: for (var i = 0; i < gPrefArray.length; ++i) michael@0: if (gFilter.test(gPrefArray[i].prefCol + ";" + gPrefArray[i].valueCol)) michael@0: gPrefView.push(gPrefArray[i]); michael@0: } michael@0: view.treebox.invalidate(); michael@0: view.treebox.rowCountChanged(oldlen, gPrefView.length - oldlen); michael@0: gotoPref(prefCol); michael@0: } michael@0: michael@0: function prefColSortFunction(x, y) michael@0: { michael@0: if (x.prefCol > y.prefCol) michael@0: return gSortDirection; michael@0: if (x.prefCol < y.prefCol) michael@0: return -gSortDirection; michael@0: return 0; michael@0: } michael@0: michael@0: function lockColSortFunction(x, y) michael@0: { michael@0: if (x.lockCol != y.lockCol) michael@0: return gSortDirection * (y.lockCol - x.lockCol); michael@0: return prefColSortFunction(x, y); michael@0: } michael@0: michael@0: function typeColSortFunction(x, y) michael@0: { michael@0: if (x.typeCol != y.typeCol) michael@0: return gSortDirection * (y.typeCol - x.typeCol); michael@0: return prefColSortFunction(x, y); michael@0: } michael@0: michael@0: function valueColSortFunction(x, y) michael@0: { michael@0: if (x.valueCol > y.valueCol) michael@0: return gSortDirection; michael@0: if (x.valueCol < y.valueCol) michael@0: return -gSortDirection; michael@0: return prefColSortFunction(x, y); michael@0: } michael@0: michael@0: const gSortFunctions = michael@0: { michael@0: prefCol: prefColSortFunction, michael@0: lockCol: lockColSortFunction, michael@0: typeCol: typeColSortFunction, michael@0: valueCol: valueColSortFunction michael@0: }; michael@0: michael@0: const configController = { michael@0: supportsCommand: function supportsCommand(command) { michael@0: return command == "cmd_copy"; michael@0: }, michael@0: isCommandEnabled: function isCommandEnabled(command) { michael@0: return view.selection && view.selection.currentIndex >= 0; michael@0: }, michael@0: doCommand: function doCommand(command) { michael@0: copyPref(); michael@0: }, michael@0: onEvent: function onEvent(event) { michael@0: } michael@0: } michael@0: michael@0: function updateContextMenu() michael@0: { michael@0: var lockCol = PREF_IS_LOCKED; michael@0: var typeCol = nsIPrefBranch.PREF_STRING; michael@0: var valueCol = ""; michael@0: var copyDisabled = true; michael@0: var prefSelected = view.selection.currentIndex >= 0; michael@0: michael@0: if (prefSelected) { michael@0: var prefRow = gPrefView[view.selection.currentIndex]; michael@0: lockCol = prefRow.lockCol; michael@0: typeCol = prefRow.typeCol; michael@0: valueCol = prefRow.valueCol; michael@0: copyDisabled = false; michael@0: } michael@0: michael@0: var copyPref = document.getElementById("copyPref"); michael@0: copyPref.setAttribute("disabled", copyDisabled); michael@0: michael@0: var copyName = document.getElementById("copyName"); michael@0: copyName.setAttribute("disabled", copyDisabled); michael@0: michael@0: var copyValue = document.getElementById("copyValue"); michael@0: copyValue.setAttribute("disabled", copyDisabled); michael@0: michael@0: var resetSelected = document.getElementById("resetSelected"); michael@0: resetSelected.setAttribute("disabled", lockCol != PREF_IS_USER_SET); michael@0: michael@0: var canToggle = typeCol == nsIPrefBranch.PREF_BOOL && valueCol != ""; michael@0: // indicates that a pref is locked or no pref is selected at all michael@0: var isLocked = lockCol == PREF_IS_LOCKED; michael@0: michael@0: var modifySelected = document.getElementById("modifySelected"); michael@0: modifySelected.setAttribute("disabled", isLocked); michael@0: modifySelected.hidden = canToggle; michael@0: michael@0: var toggleSelected = document.getElementById("toggleSelected"); michael@0: toggleSelected.setAttribute("disabled", isLocked); michael@0: toggleSelected.hidden = !canToggle; michael@0: } michael@0: michael@0: function copyPref() michael@0: { michael@0: var pref = gPrefView[view.selection.currentIndex]; michael@0: gClipboardHelper.copyString(pref.prefCol + ';' + pref.valueCol, document); michael@0: } michael@0: michael@0: function copyName() michael@0: { michael@0: gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].prefCol, document); michael@0: } michael@0: michael@0: function copyValue() michael@0: { michael@0: gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].valueCol, document); michael@0: } michael@0: michael@0: function ModifySelected() michael@0: { michael@0: if (view.selection.currentIndex >= 0) michael@0: ModifyPref(gPrefView[view.selection.currentIndex]); michael@0: } michael@0: michael@0: function ResetSelected() michael@0: { michael@0: var entry = gPrefView[view.selection.currentIndex]; michael@0: gPrefBranch.clearUserPref(entry.prefCol); michael@0: } michael@0: michael@0: function NewPref(type) michael@0: { michael@0: var result = { value: "" }; michael@0: var dummy = { value: 0 }; michael@0: if (Services.prompt.prompt(window, michael@0: gConfigBundle.getFormattedString("new_title", michael@0: [gTypeStrs[type]]), michael@0: gConfigBundle.getString("new_prompt"), michael@0: result, michael@0: null, michael@0: dummy)) { michael@0: result.value = result.value.trim(); michael@0: if (!result.value) { michael@0: return; michael@0: } michael@0: michael@0: var pref; michael@0: if (result.value in gPrefHash) michael@0: pref = gPrefHash[result.value]; michael@0: else michael@0: pref = { prefCol: result.value, lockCol: PREF_IS_DEFAULT_VALUE, typeCol: type, valueCol: "" }; michael@0: if (ModifyPref(pref)) michael@0: setTimeout(gotoPref, 0, result.value); michael@0: } michael@0: } michael@0: michael@0: function gotoPref(pref) michael@0: { michael@0: // make sure the pref exists and is displayed in the current view michael@0: var index = pref in gPrefHash ? getViewIndexOfPref(gPrefHash[pref]) : -1; michael@0: if (index >= 0) { michael@0: view.selection.select(index); michael@0: view.treebox.ensureRowIsVisible(index); michael@0: } else { michael@0: view.selection.clearSelection(); michael@0: view.selection.currentIndex = -1; michael@0: } michael@0: } michael@0: michael@0: function ModifyPref(entry) michael@0: { michael@0: if (entry.lockCol == PREF_IS_LOCKED) michael@0: return false; michael@0: var title = gConfigBundle.getFormattedString("modify_title", [gTypeStrs[entry.typeCol]]); michael@0: if (entry.typeCol == nsIPrefBranch.PREF_BOOL) { michael@0: var check = { value: entry.valueCol == "false" }; michael@0: if (!entry.valueCol && !Services.prompt.select(window, title, entry.prefCol, 2, [false, true], check)) michael@0: return false; michael@0: gPrefBranch.setBoolPref(entry.prefCol, check.value); michael@0: } else { michael@0: var result = { value: entry.valueCol }; michael@0: var dummy = { value: 0 }; michael@0: if (!Services.prompt.prompt(window, title, entry.prefCol, result, null, dummy)) michael@0: return false; michael@0: if (entry.typeCol == nsIPrefBranch.PREF_INT) { michael@0: // | 0 converts to integer or 0; - 0 to float or NaN. michael@0: // Thus, this check should catch all cases. michael@0: var val = result.value | 0; michael@0: if (val != result.value - 0) { michael@0: var err_title = gConfigBundle.getString("nan_title"); michael@0: var err_text = gConfigBundle.getString("nan_text"); michael@0: Services.prompt.alert(window, err_title, err_text); michael@0: return false; michael@0: } michael@0: gPrefBranch.setIntPref(entry.prefCol, val); michael@0: } else { michael@0: var supportsString = Components.classes[nsSupportsString_CONTRACTID].createInstance(nsISupportsString); michael@0: supportsString.data = result.value; michael@0: gPrefBranch.setComplexValue(entry.prefCol, nsISupportsString, supportsString); michael@0: } michael@0: } michael@0: michael@0: Services.prefs.savePrefFile(null); michael@0: return true; michael@0: }