1
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998
20
* the Initial Developer. All Rights Reserved.
23
* Gervase Markham <gerv@gerv.net>
24
* Tuukka Tolvanen <tt@lament.cjb.net>
26
* Alternatively, the contents of this file may be used under the terms of
27
* either the GNU General Public License Version 2 or later (the "GPL"), or
28
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
* in which case the provisions of the GPL or the LGPL are applicable instead
30
* of those above. If you wish to allow use of your version of this file only
31
* under the terms of either the GPL or the LGPL, and not to allow others to
32
* use your version of this file under the terms of the NPL, indicate your
33
* decision by deleting the provisions above and replace them with the notice
34
* and other provisions required by the GPL or the LGPL. If you do not delete
35
* the provisions above, a recipient may use your version of this file under
36
* the terms of any one of the NPL, the GPL or the LGPL.
38
* ***** END LICENSE BLOCK ***** */
40
var fontEnumerator = null;
41
var globalFonts = null;
42
var fontTypes = ["serif", "sans-serif", "cursive", "fantasy", "monospace"];
43
var variableSize, fixedSize, minSize, languageList;
44
var languageData = [];
46
var gPrefutilitiesBundle;
48
// manual data retrieval function for PrefWindow
51
var dataObject = parent.hPrefWindow.wsm.dataManager.pageData["chrome://communicator/content/pref/pref-fonts.xul"];
53
// store data for language independent widgets
54
var lists = ["selectLangs", "proportionalFont"];
55
for( var i = 0; i < lists.length; i++ )
57
if( !( "dataEls" in dataObject ) )
58
dataObject.dataEls = [];
59
dataObject.dataEls[ lists[i] ] = [];
60
dataObject.dataEls[ lists[i] ].value = document.getElementById( lists[i] ).value;
63
dataObject.defaultFont = document.getElementById( "proportionalFont" ).value;
64
dataObject.fontDPI = document.getElementById( "screenResolution" ).value;
65
dataObject.useDocFonts = document.getElementById( "browserUseDocumentFonts" ).checked ? 1 : 0;
67
// save current state for language dependent fields and store
69
dataObject.languageData = languageData;
74
// manual data setting function for PrefWindow
75
function SetFields( aDataObject )
77
languageData = "languageData" in aDataObject ? aDataObject.languageData : languageData ;
78
currentLanguage = "currentLanguage" in aDataObject ? aDataObject.currentLanguage : null ;
80
var lists = ["selectLangs", "proportionalFont"];
83
for( var i = 0; i < lists.length; i++ )
85
var element = document.getElementById( lists[i] );
86
if( "dataEls" in aDataObject )
88
element.selectedItem = element.getElementsByAttribute( "value", aDataObject.dataEls[ lists[i] ].value )[0];
92
var prefstring = element.getAttribute( "prefstring" );
93
var preftype = element.getAttribute( "preftype" );
94
if( prefstring && preftype )
96
prefvalue = parent.hPrefWindow.getPref( preftype, prefstring );
97
element.selectedItem = element.getElementsByAttribute( "value", prefvalue )[0];
102
var screenResolution = document.getElementById( "screenResolution" );
105
if( "fontDPI" in aDataObject )
107
resolution = aDataObject.fontDPI;
111
prefvalue = parent.hPrefWindow.getPref( "int", "browser.display.screen_resolution" );
112
if( prefvalue != "!/!ERROR_UNDEFINED_PREF!/!" )
113
resolution = prefvalue;
115
resolution = 96; // If it all goes horribly wrong, fall back on 96.
118
setResolution( resolution );
120
if ( parent.hPrefWindow.getPrefIsLocked( "browser.display.screen_resolution" ) ) {
121
screenResolution.disabled = true;
124
var useDocFontsCheckbox = document.getElementById( "browserUseDocumentFonts" );
125
if( "useDocFonts" in aDataObject && aDataObject.useDocFonts != undefined )
126
useDocFontsCheckbox.checked = aDataObject.useDocFonts ? true : false;
129
prefvalue = parent.hPrefWindow.getPref( "int", "browser.display.use_document_fonts" );
130
if( prefvalue != "!/!ERROR_UNDEFINED_PREF!/!" )
131
useDocFontsCheckbox.checked = prefvalue ? true : false ;
133
if ( parent.hPrefWindow.getPrefIsLocked( "browser.display.use_document_fonts" ) ) {
134
useDocFontsCheckbox.disabled = true;
140
variableSize = document.getElementById( "sizeVar" );
141
fixedSize = document.getElementById( "sizeMono" );
142
minSize = document.getElementById( "minSize" );
143
languageList = document.getElementById( "selectLangs" );
145
gPrefutilitiesBundle = document.getElementById("bundle_prefutilities");
147
// register our ok callback function
148
parent.hPrefWindow.registerOKCallbackFunc( saveFontPrefs );
150
// eventually we should detect the default language and select it by default
153
// Allow user to ask the OS for a DPI if we are under X or OS/2
154
if ((navigator.appVersion.indexOf("X11") != -1) || (navigator.appVersion.indexOf("OS/2") != -1))
156
document.getElementById( "systemResolution" ).removeAttribute( "hidden" );
159
// Set up the labels for the standard issue resolutions
161
resolution = document.getElementById( "screenResolution" );
163
// Set an attribute on the selected resolution item so we can fall back on
164
// it if an invalid selection is made (select "Other...", hit Cancel)
165
resolution.selectedItem.setAttribute("current", "true");
167
var defaultResolution;
170
// On OS/2, 120 is the default system resolution.
171
// 96 is valid, but used only for for 640x480.
172
if (navigator.appVersion.indexOf("OS/2") != -1)
174
defaultResolution = "120";
175
otherResolution = "96";
176
document.getElementById( "arbitraryResolution" ).setAttribute( "hidden", "true" );
177
document.getElementById( "resolutionSeparator" ).setAttribute( "hidden", "true" );
179
defaultResolution = "96";
180
otherResolution = "72";
183
var dpi = resolution.getAttribute( "dpi" );
184
resolution = document.getElementById( "defaultResolution" );
185
resolution.setAttribute( "value", defaultResolution );
186
resolution.setAttribute( "label", dpi.replace(/\$val/, defaultResolution ) );
187
resolution = document.getElementById( "otherResolution" );
188
resolution.setAttribute( "value", otherResolution );
189
resolution.setAttribute( "label", dpi.replace(/\$val/, otherResolution ) );
191
// Get the pref and set up the dialog appropriately. Startup is called
192
// after SetFields so we can't rely on that call to do the business.
193
var prefvalue = parent.hPrefWindow.getPref( "int", "browser.display.screen_resolution" );
194
if( prefvalue != "!/!ERROR_UNDEFINED_PREF!/!" )
195
resolution = prefvalue;
197
resolution = 96; // If it all goes horribly wrong, fall back on 96.
199
setResolution( resolution );
201
// This prefstring is a contrived pref whose sole purpose is to lock some
202
// elements in this panel. The value of the pref is not used and does not matter.
203
if ( parent.hPrefWindow.getPrefIsLocked( "browser.display.languageList" ) ) {
204
disableAllFontElements();
208
function getFontEnumerator()
212
fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
214
.QueryInterface(Components.interfaces.nsIFontEnumerator);
216
return fontEnumerator;
219
function listElement( aListID )
221
this.listElement = document.getElementById( aListID );
224
listElement.prototype =
229
// remove the menupopup node child of the menulist.
230
this.listElement.removeChild( this.listElement.firstChild );
234
function ( aLanguage, aFontType )
237
var defaultFont = null;
238
var count = { value: 0 };
239
var fonts = getFontEnumerator().EnumerateFonts( aLanguage, aFontType, count );
240
if (fonts.length > 0)
242
defaultFont = getFontEnumerator().getDefaultFont( aLanguage, aFontType );
246
// if no specific fonts, relax 'aFontType' and try to get other
247
// fonts for this language so that we can group them on top
248
fonts = getFontEnumerator().EnumerateFonts( aLanguage, "", count );
249
if (fonts.length > 0)
251
defaultFont = getFontEnumerator().getDefaultFont( aLanguage, "" );
256
var separatorNode = null;
257
var popupNode = document.createElement( "menupopup" );
259
if (fonts.length > 0)
261
// always put the default font at the front of the list
264
var label = gPrefutilitiesBundle
265
.getString("labelDefaultFont")
266
.replace(/%font_family%/, defaultFont);
267
itemNode = document.createElement( "menuitem" );
268
itemNode.setAttribute( "label", label );
269
itemNode.setAttribute( "value", "" ); // special blank value
270
popupNode.appendChild( itemNode );
272
separatorNode = document.createElement( "menuseparator" );
273
popupNode.appendChild( separatorNode );
276
for (i = 0; i < fonts.length; i++)
278
itemNode = document.createElement( "menuitem" );
279
itemNode.setAttribute( "value", fonts[i] );
280
itemNode.setAttribute( "label", fonts[i] );
281
popupNode.appendChild( itemNode );
285
// get all the fonts to complete the font lists
288
globalFonts = getFontEnumerator().EnumerateAllFonts( count );
291
// since the lists are sorted, we can get unique entries by just walking
292
// both lists linearly side-by-side, skipping those values already in
294
if (globalFonts.length > fonts.length)
296
var menuItem = separatorNode ? separatorNode.nextSibling : popupNode.firstChild;
297
var menuValue = menuItem ? menuItem.getAttribute( "value" ) : null;
299
separatorNode = document.createElement( "menuseparator" );
300
popupNode.appendChild( separatorNode );
302
for (i = 0; i < globalFonts.length; i++)
304
if (globalFonts[i] != menuValue)
306
itemNode = document.createElement( "menuitem" );
307
itemNode.setAttribute( "value", globalFonts[i] );
308
itemNode.setAttribute( "label", globalFonts[i] );
309
popupNode.appendChild( itemNode );
313
menuItem = menuItem.nextSibling;
314
menuValue = menuItem ? menuItem.getAttribute( "value" ) : null;
319
this.listElement.appendChild( popupNode );
321
return popupNode.firstChild;
325
function lazyAppendFontNames( i )
327
// schedule the build of the next font list
328
if (i+1 < fontTypes.length)
330
window.setTimeout(lazyAppendFontNames, 100, i+1);
333
// now build and populate the fonts for the requested font type
334
var defaultItem = null;
335
var selectElement = new listElement( fontTypes[i] );
336
selectElement.clearList();
339
defaultItem = selectElement.appendFontNames( languageList.value, fontTypes[i] );
342
dump("pref-fonts.js: " + e + "\nFailed to build the font list for " + fontTypes[i] + "\n");
346
// now set the selected font item for the drop down list
349
return; // nothing to select, so no need to bother
351
// the item returned by default is our last resort fall-back
352
var selectedItem = defaultItem;
353
if( languageList.value in languageData )
355
// data exists for this language, pre-select items based on this information
356
var dataVal = languageData[languageList.value].types[fontTypes[i]];
357
if (!dataVal.length) // special blank means the default
359
selectedItem = defaultItem;
363
var dataEls = selectElement.listElement.getElementsByAttribute( "value", dataVal );
364
selectedItem = dataEls.length ? dataEls[0] : defaultItem;
371
var fontPrefString = "font.name." + fontTypes[i] + "." + languageList.value;
372
var selectVal = parent.hPrefWindow.pref.getComplexValue( fontPrefString, Components.interfaces.nsISupportsString ).data;
373
var dataEls = selectElement.listElement.getElementsByAttribute( "value", selectVal );
375
// we need to honor name-list in case name is unavailable
376
if (!dataEls.length) {
377
var fontListPrefString = "font.name-list." + fontTypes[i] + "." + languageList.value;
378
var nameList = parent.hPrefWindow.pref.getComplexValue( fontListPrefString, Components.interfaces.nsISupportsString ).data;
379
var fontNames = nameList.split(",");
380
var stripWhitespace = /^\s*(.*)\s*$/;
382
for (j = 0; j < fontNames.length; j++) {
383
selectVal = fontNames[j].replace(stripWhitespace, "$1");
384
dataEls = selectElement.listElement.getElementsByAttribute("value", selectVal);
386
break; // exit loop if we find one
389
selectedItem = dataEls.length ? dataEls[0] : defaultItem;
392
selectedItem = defaultItem;
396
selectElement.listElement.selectedItem = selectedItem;
397
selectElement.listElement.removeAttribute( "disabled" );
400
function saveFontPrefs()
403
var dataObject = parent.hPrefWindow.wsm.dataManager.pageData["chrome://communicator/content/pref/pref-fonts.xul"];
404
var pref = parent.hPrefWindow.pref;
405
for( var language in dataObject.languageData )
407
for( var type in dataObject.languageData[language].types )
409
var fontPrefString = "font.name." + type + "." + language;
413
currValue = pref.getComplexValue( fontPrefString, Components.interfaces.nsISupportsString ).data;
419
var dataValue = dataObject.languageData[language].types[type];
420
if( currValue != dataValue )
424
parent.hPrefWindow.setPref( "string", fontPrefString, dataValue );
428
// A font name can't be blank. The special blank means the default.
429
// Unset the pref entirely, letting Gfx to decide. GfxXft will use what
430
// Xft says, whereas GfxWin and others will use the built-in settings
431
// that are shipped for font.name and font.name-list.
434
// ClearUserPref throws an exception...
435
pref.clearUserPref( fontPrefString );
443
var variableSizePref = "font.size.variable." + language;
444
var fixedSizePref = "font.size.fixed." + language;
445
var minSizePref = "font.minimum-size." + language;
446
var currVariableSize = 12, currFixedSize = 12, minSizeVal = 0;
449
currVariableSize = pref.getIntPref( variableSizePref );
450
currFixedSize = pref.getIntPref( fixedSizePref );
451
minSizeVal = pref.getIntPref( minSizePref );
456
if( currVariableSize != dataObject.languageData[language].variableSize )
457
pref.setIntPref( variableSizePref, dataObject.languageData[language].variableSize );
458
if( currFixedSize != dataObject.languageData[language].fixedSize )
459
pref.setIntPref( fixedSizePref, dataObject.languageData[language].fixedSize );
460
if ( minSizeVal != dataObject.languageData[language].minSize ) {
461
pref.setIntPref ( minSizePref, dataObject.languageData[language].minSize );
466
var fontDPI = parseInt( dataObject.fontDPI );
467
var documentFonts = dataObject.useDocFonts;
468
var defaultFont = dataObject.defaultFont;
472
var currDPI = pref.getIntPref( "browser.display.screen_resolution" );
473
var currFonts = pref.getIntPref( "browser.display.use_document_fonts" );
474
var currDefault = pref.getComplexValue( "font.default", Components.interfaces.nsISupportsString ).data;
479
if( currDPI != fontDPI )
480
pref.setIntPref( "browser.display.screen_resolution", fontDPI );
481
if( currFonts != documentFonts )
482
pref.setIntPref( "browser.display.use_document_fonts", documentFonts );
483
if( currDefault != defaultFont )
485
parent.hPrefWindow.setPref( "string", "font.default", defaultFont );
491
for( var i = 0; i < fontTypes.length; i++ )
493
// preliminary initialisation
494
if( currentLanguage && !( currentLanguage in languageData ) )
495
languageData[currentLanguage] = [];
496
if( currentLanguage && !( "types" in languageData[currentLanguage] ) )
497
languageData[currentLanguage].types = [];
498
// save data for the previous language
499
if( currentLanguage && currentLanguage in languageData &&
500
"types" in languageData[currentLanguage] )
501
languageData[currentLanguage].types[fontTypes[i]] = document.getElementById( fontTypes[i] ).value;
504
if( currentLanguage && currentLanguage in languageData &&
505
"types" in languageData[currentLanguage] )
507
languageData[currentLanguage].variableSize = parseInt( variableSize.value );
508
languageData[currentLanguage].fixedSize = parseInt( fixedSize.value );
509
languageData[currentLanguage].minSize = parseInt( minSize.value );
513
// Selects size (or the nearest entry that exists in the list)
514
// in the menulist minSize
515
function minSizeSelect(size)
517
var items = minSize.getElementsByAttribute( "value", size );
518
if (items.length > 0)
519
minSize.selectedItem = items[0];
525
minSizeSelect(size - 1);
528
function selectLanguage()
530
// save current state
533
if( !currentLanguage )
534
currentLanguage = languageList.value;
535
else if( currentLanguage == languageList.value )
536
return; // same as before, nothing changed
538
// lazily populate the successive font lists at 100ms intervals.
539
// (Note: the third parameter to setTimeout() is going to be
540
// passed as argument to the callback function.)
541
window.setTimeout(lazyAppendFontNames, 100, 0);
543
// in the meantime, disable the menu lists
544
for( var i = 0; i < fontTypes.length; i++ )
546
var listElement = document.getElementById( fontTypes[i] );
547
listElement.setAttribute( "value", "" );
548
listElement.setAttribute( "label", "" );
549
listElement.setAttribute( "disabled", "true" );
552
// and set the font sizes
555
var variableSizePref = "font.size.variable." + languageList.value;
556
var sizeVarVal = parent.hPrefWindow.pref.getIntPref( variableSizePref );
557
variableSize.selectedItem = variableSize.getElementsByAttribute( "value", sizeVarVal )[0];
559
var fixedSizePref = "font.size.fixed." + languageList.value;
560
var sizeFixedVal = parent.hPrefWindow.pref.getIntPref( fixedSizePref );
561
fixedSize.selectedItem = fixedSize.getElementsByAttribute( "value", sizeFixedVal )[0];
563
catch(e) { } // font size lists can simply default to the first entry
568
var minSizePref = "font.minimum-size." + languageList.value;
569
minSizeVal = parent.hPrefWindow.pref.getIntPref( minSizePref );
572
minSizeSelect( minSizeVal );
574
currentLanguage = languageList.value;
577
function changeScreenResolution()
579
var screenResolution = document.getElementById("screenResolution");
580
var userResolution = document.getElementById("userResolution");
582
var previousSelection = screenResolution.getElementsByAttribute("current", "true")[0];
584
if (screenResolution.value == "other")
586
// If the user selects "Other..." we bring up the calibrate screen dialog
587
var rv = { newdpi : 0 };
588
var calscreen = window.openDialog("chrome://communicator/content/pref/pref-calibrate-screen.xul",
590
"modal,chrome,centerscreen,resizable=no,titlebar",
594
// They have entered values, and we have a DPI value back
595
var dpi = screenResolution.getAttribute( "dpi" );
596
setResolution ( rv.newdpi );
598
previousSelection.removeAttribute("current");
599
screenResolution.selectedItem.setAttribute("current", "true");
603
// They've cancelled. We can't leave "Other..." selected, so...
604
// we re-select the previously selected item.
605
screenResolution.selectedItem = previousSelection;
608
else if (!(screenResolution.value == userResolution.value))
610
// User has selected one of the hard-coded resolutions
611
userResolution.setAttribute("hidden", "true");
613
previousSelection.removeAttribute("current");
614
screenResolution.selectedItem.setAttribute("current", "true");
618
function setResolution( resolution )
620
// Given a number, if it's equal to a hard-coded resolution we use that,
621
// otherwise we set the userResolution field.
622
var screenResolution = document.getElementById( "screenResolution" );
623
var userResolution = document.getElementById( "userResolution" );
625
var items = screenResolution.getElementsByAttribute( "value", resolution );
628
// If it's one of the hard-coded values, we'll select it directly
629
screenResolution.selectedItem = items[0];
630
userResolution.setAttribute( "hidden", "true" );
634
// Otherwise we need to set up the userResolution field
635
var dpi = screenResolution.getAttribute( "dpi" );
636
userResolution.setAttribute( "value", resolution );
637
userResolution.setAttribute( "label", dpi.replace(/\$val/, resolution) );
638
userResolution.removeAttribute( "hidden" );
639
screenResolution.selectedItem = userResolution;
643
// "Calibrate screen" dialog code
648
doSetOKCancel(onOK, onCancel);
649
document.getElementById("horizSize").focus();
654
// Get value from the dialog to work out dpi
655
var horizSize = parseFloat(document.getElementById("horizSize").value);
656
var units = document.getElementById("units").value;
658
if (!horizSize || horizSize < 0)
660
// We can't calculate anything without a proper value
661
window.arguments[0].newdpi = -1;
665
// Convert centimetres to inches.
666
// The magic number is allowed because it's a fundamental constant :-)
667
if (units === "centimetres")
672
// These shouldn't change, but you can't be too careful.
673
var horizBarLengthPx = document.getElementById("horizRuler").boxObject.width;
675
var horizDPI = parseInt(horizBarLengthPx) / horizSize;
677
// Average the two <shrug>.
678
window.arguments[0].newdpi = Math.round(horizDPI);
685
// We return -1 to show that no value has been given.
686
window.arguments[0].newdpi = -1;
690
// disable font items, but not the browserUseDocumentFonts checkbox nor the resolution
692
function disableAllFontElements()
694
var doc_ids = [ "selectLangs", "proportionalFont",
695
"sizeVar", "serif", "sans-serif",
696
"cursive", "fantasy", "monospace",
697
"sizeMono", "minSize" ];
698
for (i=0; i<doc_ids.length; i++) {
699
element = document.getElementById( doc_ids[i] );
700
element.disabled = true;