/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Gervase Markham * Tuukka Tolvanen * Stefan Borggraefe * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var fontEnumerator = null; var globalFonts = null; var fontTypes = ["serif", "sans-serif", "cursive", "fantasy", "monospace"]; var defaultFont, variableSize, fixedSize, minSize, languageList; var languageData = []; var currentLanguage; var gPrefutilitiesBundle; // manual data retrieval function for PrefWindow function GetFields() { var dataObject = parent.hPrefWindow.wsm.dataManager.pageData["chrome://communicator/content/pref/pref-fonts.xul"]; // store data for language independent widgets if( !( "dataEls" in dataObject ) ) dataObject.dataEls = []; dataObject.dataEls[ "selectLangs" ] = []; dataObject.dataEls[ "selectLangs" ].value = document.getElementById( "selectLangs" ).value; dataObject.useDocFonts = document.getElementById( "browserUseDocumentFonts" ).checked ? 1 : 0; // save current state for language dependent fields and store saveState(); dataObject.languageData = languageData; return dataObject; } // manual data setting function for PrefWindow function SetFields( aDataObject ) { languageData = "languageData" in aDataObject ? aDataObject.languageData : languageData ; currentLanguage = "currentLanguage" in aDataObject ? aDataObject.currentLanguage : null ; var element = document.getElementById( "selectLangs" ); if( "dataEls" in aDataObject ) { element.selectedItem = element.getElementsByAttribute( "value", aDataObject.dataEls[ "selectLangs" ].value )[0]; } else { var prefstring = element.getAttribute( "prefstring" ); var preftype = element.getAttribute( "preftype" ); if( prefstring && preftype ) { var prefvalue = parent.hPrefWindow.getPref( preftype, prefstring ); element.selectedItem = element.getElementsByAttribute( "value", prefvalue )[0]; } } var useDocFontsCheckbox = document.getElementById( "browserUseDocumentFonts" ); if( "useDocFonts" in aDataObject && aDataObject.useDocFonts != undefined ) useDocFontsCheckbox.checked = aDataObject.useDocFonts ? true : false; else { prefvalue = parent.hPrefWindow.getPref( "int", "browser.display.use_document_fonts" ); if( prefvalue != "!/!ERROR_UNDEFINED_PREF!/!" ) useDocFontsCheckbox.checked = prefvalue ? true : false ; } if ( parent.hPrefWindow.getPrefIsLocked( "browser.display.use_document_fonts" ) ) { useDocFontsCheckbox.disabled = true; } } function Startup() { defaultFont = document.getElementById( "proportionalFont" ); variableSize = document.getElementById( "sizeVar" ); fixedSize = document.getElementById( "sizeMono" ); minSize = document.getElementById( "minSize" ); languageList = document.getElementById( "selectLangs" ); gPrefutilitiesBundle = document.getElementById("bundle_prefutilities"); // register our ok callback function parent.hPrefWindow.registerOKCallbackFunc( saveFontPrefs ); // eventually we should detect the default language and select it by default selectLanguage(); // This prefstring is a contrived pref whose sole purpose is to lock some // elements in this panel. The value of the pref is not used and does not matter. if ( parent.hPrefWindow.getPrefIsLocked( "browser.display.languageList" ) ) { disableAllFontElements(); } } function getFontEnumerator() { if (!fontEnumerator) { fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"] .createInstance() .QueryInterface(Components.interfaces.nsIFontEnumerator); } return fontEnumerator; } function listElement( aListID ) { this.listElement = document.getElementById( aListID ); } listElement.prototype = { clearList: function () { // remove the menupopup node child of the menulist. this.listElement.removeChild( this.listElement.firstChild ); }, appendFontNames: function ( aLanguage, aFontType ) { var i; var defaultFont = null; var count = { value: 0 }; var fonts = getFontEnumerator().EnumerateFonts( aLanguage, aFontType, count ); if (fonts.length > 0) { defaultFont = getFontEnumerator().getDefaultFont( aLanguage, aFontType ); } else { // if no specific fonts, relax 'aFontType' and try to get other // fonts for this language so that we can group them on top fonts = getFontEnumerator().EnumerateFonts( aLanguage, "", count ); if (fonts.length > 0) { defaultFont = getFontEnumerator().getDefaultFont( aLanguage, "" ); } } var itemNode = null; var separatorNode = null; var popupNode = document.createElement( "menupopup" ); if (fonts.length > 0) { // always put the default font at the front of the list if (defaultFont) { var label = gPrefutilitiesBundle .getString("labelDefaultFont") .replace(/%font_family%/, defaultFont); itemNode = document.createElement( "menuitem" ); itemNode.setAttribute( "label", label ); itemNode.setAttribute( "value", "" ); // special blank value popupNode.appendChild( itemNode ); separatorNode = document.createElement( "menuseparator" ); popupNode.appendChild( separatorNode ); } for (i = 0; i < fonts.length; i++) { itemNode = document.createElement( "menuitem" ); itemNode.setAttribute( "value", fonts[i] ); itemNode.setAttribute( "label", fonts[i] ); popupNode.appendChild( itemNode ); } } // get all the fonts to complete the font lists if (!globalFonts) { globalFonts = getFontEnumerator().EnumerateAllFonts( count ); } // since the lists are sorted, we can get unique entries by just walking // both lists linearly side-by-side, skipping those values already in // the popup list if (globalFonts.length > fonts.length) { var menuItem = separatorNode ? separatorNode.nextSibling : popupNode.firstChild; var menuValue = menuItem ? menuItem.getAttribute( "value" ) : null; separatorNode = document.createElement( "menuseparator" ); popupNode.appendChild( separatorNode ); for (i = 0; i < globalFonts.length; i++) { if (globalFonts[i] != menuValue) { itemNode = document.createElement( "menuitem" ); itemNode.setAttribute( "value", globalFonts[i] ); itemNode.setAttribute( "label", globalFonts[i] ); popupNode.appendChild( itemNode ); } else { menuItem = menuItem.nextSibling; menuValue = menuItem ? menuItem.getAttribute( "value" ) : null; } } } this.listElement.appendChild( popupNode ); return popupNode.firstChild; } }; function lazyAppendFontNames( i ) { // schedule the build of the next font list if (i+1 < fontTypes.length) { window.setTimeout(lazyAppendFontNames, 100, i+1); } // now build and populate the fonts for the requested font type var defaultItem; var selectElement = new listElement( fontTypes[i] ); selectElement.clearList(); try { defaultItem = selectElement.appendFontNames( languageList.value, fontTypes[i] ); } catch(e) { dump("pref-fonts.js: " + e + "\nFailed to build the font list for " + fontTypes[i] + "\n"); return; } // now set the selected font item for the drop down list if (!defaultItem) return; // nothing to select, so no need to bother // the item returned by default is our last resort fall-back var selectedItem = defaultItem; var dataEls; if( languageList.value in languageData ) { // data exists for this language, pre-select items based on this information var dataVal = languageData[languageList.value].types[fontTypes[i]]; if (dataVal.length) // else: special blank means the default dataEls = selectElement.listElement.getElementsByAttribute("value", dataVal); } else { try { var fontPrefString = "font.name." + fontTypes[i] + "." + languageList.value; var selectVal = parent.hPrefWindow.pref.getComplexValue( fontPrefString, Components.interfaces.nsISupportsString ).data; dataEls = selectElement.listElement.getElementsByAttribute("value", selectVal); // we need to honor name-list in case name is unavailable if (!dataEls.item(0)) { var fontListPrefString = "font.name-list." + fontTypes[i] + "." + languageList.value; var nameList = parent.hPrefWindow.pref.getComplexValue( fontListPrefString, Components.interfaces.nsISupportsString ).data; var fontNames = nameList.split(","); for (j = 0; j < fontNames.length; j++) { selectVal = fontNames[j].replace(/^\s+|\s+$/, ""); dataEls = selectElement.listElement.getElementsByAttribute("value", selectVal); if (dataEls.item(0)) break; // exit loop if we find one } } } catch(e) { } } if (dataEls && dataEls.item(0)) selectedItem = dataEls[0]; selectElement.listElement.selectedItem = selectedItem; selectElement.listElement.removeAttribute( "disabled" ); } function saveFontPrefs() { // saving font prefs var dataObject = parent.hPrefWindow.wsm.dataManager.pageData["chrome://communicator/content/pref/pref-fonts.xul"]; var pref = parent.hPrefWindow.pref; for( var language in dataObject.languageData ) { for( var type in dataObject.languageData[language].types ) { var fontPrefString = "font.name." + type + "." + language; var currValue = ""; try { currValue = pref.getComplexValue( fontPrefString, Components.interfaces.nsISupportsString ).data; } catch(e) { } var dataValue = dataObject.languageData[language].types[type]; if( currValue != dataValue ) { if (dataValue) { parent.hPrefWindow.setPref( "string", fontPrefString, dataValue ); } else { // A font name can't be blank. The special blank means the default. // Unset the pref entirely, letting Gfx to decide. GfxXft will use what // Xft says, whereas GfxWin and others will use the built-in settings // that are shipped for font.name and font.name-list. try { // ClearUserPref throws an exception... pref.clearUserPref( fontPrefString ); } catch(e) { } } } } var defaultFontPref = "font.default." + language; var variableSizePref = "font.size.variable." + language; var fixedSizePref = "font.size.fixed." + language; var minSizePref = "font.minimum-size." + language; var currDefaultFont = "serif", currVariableSize = 12, currFixedSize = 12, minSizeVal = 0; try { currDefaultFont = parent.hPrefWindow.getPref( "string", defaultFontPref ); currVariableSize = pref.getIntPref( variableSizePref ); currFixedSize = pref.getIntPref( fixedSizePref ); minSizeVal = pref.getIntPref( minSizePref ); } catch(e) { } if( currDefaultFont != dataObject.languageData[language].defaultFont ) parent.hPrefWindow.setPref( "string", defaultFontPref, dataObject.languageData[language].defaultFont ); if( currVariableSize != dataObject.languageData[language].variableSize ) pref.setIntPref( variableSizePref, dataObject.languageData[language].variableSize ); if( currFixedSize != dataObject.languageData[language].fixedSize ) pref.setIntPref( fixedSizePref, dataObject.languageData[language].fixedSize ); if( minSizeVal != dataObject.languageData[language].minSize ) { pref.setIntPref ( minSizePref, dataObject.languageData[language].minSize ); } } // font scaling var documentFonts = dataObject.useDocFonts; var defaultFont = dataObject.defaultFont; try { var currFonts = pref.getIntPref( "browser.display.use_document_fonts" ); } catch(e) { } if( currFonts != documentFonts ) pref.setIntPref( "browser.display.use_document_fonts", documentFonts ); } function saveState() { for( var i = 0; i < fontTypes.length; i++ ) { // preliminary initialisation if( currentLanguage && !( currentLanguage in languageData ) ) languageData[currentLanguage] = []; if( currentLanguage && !( "types" in languageData[currentLanguage] ) ) languageData[currentLanguage].types = []; // save data for the previous language if( currentLanguage && currentLanguage in languageData && "types" in languageData[currentLanguage] ) languageData[currentLanguage].types[fontTypes[i]] = document.getElementById( fontTypes[i] ).value; } if( currentLanguage && currentLanguage in languageData && "types" in languageData[currentLanguage] ) { languageData[currentLanguage].defaultFont = defaultFont.value; languageData[currentLanguage].variableSize = parseInt( variableSize.value ); languageData[currentLanguage].fixedSize = parseInt( fixedSize.value ); languageData[currentLanguage].minSize = parseInt( minSize.value ); } } // Selects size (or the nearest entry that exists in the list) // in the menulist minSize function minSizeSelect(size) { var items = minSize.getElementsByAttribute( "value", size ); if (items.item(0)) minSize.selectedItem = items[0]; else if (size < 6) minSizeSelect(6); else if (size > 24) minSizeSelect(24); else minSizeSelect(size - 1); } function selectLanguage() { // save current state saveState(); if( !currentLanguage ) currentLanguage = languageList.value; else if( currentLanguage == languageList.value ) return; // same as before, nothing changed // lazily populate the successive font lists at 100ms intervals. // (Note: the third parameter to setTimeout() is going to be // passed as argument to the callback function.) window.setTimeout(lazyAppendFontNames, 100, 0); // in the meantime, disable the menu lists for( var i = 0; i < fontTypes.length; i++ ) { var listElement = document.getElementById( fontTypes[i] ); listElement.setAttribute( "value", "" ); listElement.setAttribute( "label", "" ); listElement.setAttribute( "disabled", "true" ); } // and set the default font type and the font sizes try { defaultFont.value = parent.hPrefWindow.getPref("string", "font.default." + languageList.value); var variableSizePref = "font.size.variable." + languageList.value; var sizeVarVal = parent.hPrefWindow.pref.getIntPref( variableSizePref ); variableSize.selectedItem = variableSize.getElementsByAttribute( "value", sizeVarVal )[0]; var fixedSizePref = "font.size.fixed." + languageList.value; var sizeFixedVal = parent.hPrefWindow.pref.getIntPref( fixedSizePref ); fixedSize.selectedItem = fixedSize.getElementsByAttribute( "value", sizeFixedVal )[0]; } catch(e) { } // font size lists can simply default to the first entry var minSizeVal = 0; try { var minSizePref = "font.minimum-size." + languageList.value; minSizeVal = parent.hPrefWindow.pref.getIntPref( minSizePref ); } catch(e) { } minSizeSelect( minSizeVal ); currentLanguage = languageList.value; } // disable font items, but not the browserUseDocumentFonts checkbox function disableAllFontElements() { var doc_ids = [ "selectLangs", "proportionalFont", "sizeVar", "serif", "sans-serif", "cursive", "fantasy", "monospace", "sizeMono", "minSize" ]; for (i=0; i