diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index ea937e33f1b8..eeec02a40dd6 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -1179,6 +1179,9 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) if (!targetNode) return; + // Note: For universal/global ARIA states and properties we don't care if + // there is an ARIA role present or not. + if (aAttribute == nsAccessibilityAtoms::aria_required) { nsRefPtr event = new nsAccStateChangeEvent(targetNode, @@ -1209,6 +1212,24 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) return; } + // For aria drag and drop changes we fire a generic attribute change event; + // at least until native API comes up with a more meaningful event. + if (aAttribute == nsAccessibilityAtoms::aria_grabbed || + aAttribute == nsAccessibilityAtoms::aria_dropeffect) { + FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, + targetNode); + } + + // We treat aria-expanded as a global ARIA state for historical reasons + if (aAttribute == nsAccessibilityAtoms::aria_expanded) { + nsRefPtr event = + new nsAccStateChangeEvent(targetNode, + nsIAccessibleStates::STATE_EXPANDED, + PR_FALSE); + FireDelayedAccessibleEvent(event); + return; + } + if (!aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) { // We don't care about these other ARIA attribute changes unless there is // an ARIA role set for the element @@ -1249,15 +1270,6 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) return; } - if (aAttribute == nsAccessibilityAtoms::aria_expanded) { - nsRefPtr event = - new nsAccStateChangeEvent(targetNode, - nsIAccessibleStates::STATE_EXPANDED, - PR_FALSE); - FireDelayedAccessibleEvent(event); - return; - } - if (aAttribute == nsAccessibilityAtoms::aria_readonly) { nsRefPtr event = new nsAccStateChangeEvent(targetNode, @@ -1290,14 +1302,6 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE); return; } - - // For aria drag and drop changes we fire a generic attribute change event; - // at least until native API comes up with a more meaningful event. - if (aAttribute == nsAccessibilityAtoms::aria_grabbed || - aAttribute == nsAccessibilityAtoms::aria_dropeffect) { - FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, - targetNode); - } } void nsDocAccessible::ContentAppended(nsIDocument *aDocument, diff --git a/accessible/tests/mochitest/events/Makefile.in b/accessible/tests/mochitest/events/Makefile.in index c95ddb5ce7f2..4cccd0b5bbb7 100644 --- a/accessible/tests/mochitest/events/Makefile.in +++ b/accessible/tests/mochitest/events/Makefile.in @@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES =\ focus.html \ scroll.html \ + test_aria_statechange.html \ test_attrs.html \ test_caretmove.html \ $(warning test_coalescence.html temporarily disabled) \ diff --git a/accessible/tests/mochitest/events/test_aria_statechange.html b/accessible/tests/mochitest/events/test_aria_statechange.html new file mode 100644 index 000000000000..2a8f20ae9294 --- /dev/null +++ b/accessible/tests/mochitest/events/test_aria_statechange.html @@ -0,0 +1,85 @@ + + + + ARIA state change event testing + + + + + + + + + + + + + + + + + Mozilla Bug 551684 + + +

+ +
+  
+
+ + + + + + + diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 58d5a463b245..d66b9d3de730 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -844,9 +844,6 @@ pref("browser.zoom.siteSpecific", true); // Whether or not to update background tabs to the current zoom level. pref("browser.zoom.updateBackgroundTabs", true); -// replace newlines with spaces when pasting into fields -pref("editor.singleLine.pasteNewlines", 2); - // The breakpad report server to link to in about:crashes pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/"); diff --git a/browser/base/content/browser-tabPreviews.js b/browser/base/content/browser-tabPreviews.js index 38fc6fc99d88..3a31aa7cc948 100644 --- a/browser/base/content/browser-tabPreviews.js +++ b/browser/base/content/browser-tabPreviews.js @@ -44,18 +44,26 @@ var tabPreviews = { aspectRatio: 0.5625, // 16:9 init: function tabPreviews_init() { + if (this._selectedTab) + return; + this._selectedTab = gBrowser.selectedTab; + this.width = Math.ceil(screen.availWidth / 5.75); this.height = Math.round(this.width * this.aspectRatio); + window.addEventListener("unload", this, false); gBrowser.tabContainer.addEventListener("TabSelect", this, false); gBrowser.tabContainer.addEventListener("SSTabRestored", this, false); }, uninit: function tabPreviews_uninit() { + window.removeEventListener("unload", this, false); gBrowser.tabContainer.removeEventListener("TabSelect", this, false); gBrowser.tabContainer.removeEventListener("SSTabRestored", this, false); this._selectedTab = null; }, get: function tabPreviews_get(aTab) { + this.init(); + if (aTab.__thumbnail_lastURI && aTab.__thumbnail_lastURI != aTab.linkedBrowser.currentURI.spec) { aTab.__thumbnail = null; @@ -64,6 +72,8 @@ var tabPreviews = { return aTab.__thumbnail || this.capture(aTab, !aTab.hasAttribute("busy")); }, capture: function tabPreviews_capture(aTab, aStore) { + this.init(); + var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); thumbnail.mozOpaque = true; thumbnail.height = this.height; @@ -105,6 +115,9 @@ var tabPreviews = { case "SSTabRestored": this.capture(event.target, true); break; + case "unload": + this.uninit(); + break; } } }; @@ -225,6 +238,8 @@ var ctrlTab = { init: function ctrlTab_init() { if (!this._recentlyUsedTabs) { + tabPreviews.init(); + this._recentlyUsedTabs = [gBrowser.selectedTab]; this._init(true); } @@ -577,6 +592,8 @@ var allTabs = { return; this._initiated = true; + tabPreviews.init(); + Array.forEach(gBrowser.tabs, function (tab) { this._addPreview(tab); }, this); diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 5502e4e582a4..fd57222961f1 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1307,7 +1307,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) { // themselves. gBrowser.addEventListener("command", BrowserOnCommand, false); - tabPreviews.init(); ctrlTab.readPref(); gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false); gPrefService.addObserver(allTabs.prefName, allTabs, false); @@ -1373,7 +1372,6 @@ function BrowserShutdown() gPrefService.removeObserver(ctrlTab.prefName, ctrlTab); gPrefService.removeObserver(allTabs.prefName, allTabs); - tabPreviews.uninit(); ctrlTab.uninit(); allTabs.uninit(); @@ -7341,6 +7339,10 @@ let gPrivateBrowsingUI = { } } + if (gURLBar) { + gURLBar.editor.transactionManager.clear(); + } + document.getElementById("menu_import").removeAttribute("disabled"); // Re-enable the Clear Recent History... menu item on exit of PB mode diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 976ab11d8fd7..9662b9bb64c1 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -100,10 +100,6 @@ function nsContextMenu(aXulMenu, aBrowser) { // Prototype for nsContextMenu "class." nsContextMenu.prototype = { - // onDestroy is a no-op at this point. - onDestroy: function () { - }, - // Initialize context menu. initMenu: function CM_initMenu(aPopup, aBrowser) { this.menu = aPopup; diff --git a/browser/base/content/test/browser_bug484315.js b/browser/base/content/test/browser_bug484315.js index ff395b7dc0e4..fb23ae33a43d 100644 --- a/browser/base/content/test/browser_bug484315.js +++ b/browser/base/content/test/browser_bug484315.js @@ -1,8 +1,6 @@ function test() { var contentWin = window.open("about:blank", "", "width=100,height=100"); - var enumerator = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + var enumerator = Services.wm.getEnumerator("navigator:browser"); while (enumerator.hasMoreElements()) { let win = enumerator.getNext(); diff --git a/browser/base/content/test/browser_getshortcutoruri.js b/browser/base/content/test/browser_getshortcutoruri.js index 52dfc2912094..1b319ded812d 100644 --- a/browser/base/content/test/browser_getshortcutoruri.js +++ b/browser/base/content/test/browser_getshortcutoruri.js @@ -100,8 +100,6 @@ function test() { var gBMFolder = null; var gAddedEngines = []; function setupKeywords() { - var searchService = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); gBMFolder = Application.bookmarks.menu.addFolder("keyword-test"); for each (var item in testData) { var data = item[0]; @@ -113,8 +111,8 @@ function setupKeywords() { } if (data instanceof searchKeywordData) { - searchService.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec); - var addedEngine = searchService.getEngineByName(data.keyword); + Services.search.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec); + var addedEngine = Services.search.getEngineByName(data.keyword); if (data.postData) { var [paramName, paramValue] = data.postData.split("="); addedEngine.addParam(paramName, paramValue, null); @@ -126,8 +124,6 @@ function setupKeywords() { } function cleanupKeywords() { - var searchService = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); gBMFolder.remove(); - gAddedEngines.map(searchService.removeEngine); + gAddedEngines.map(Services.search.removeEngine); } diff --git a/browser/base/content/test/browser_pageInfo.js b/browser/base/content/test/browser_pageInfo.js index 766223cebb35..9c088840d992 100644 --- a/browser/base/content/test/browser_pageInfo.js +++ b/browser/base/content/test/browser_pageInfo.js @@ -1,5 +1,3 @@ -var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - function test() { waitForExplicitFinish(); @@ -8,7 +6,7 @@ function test() { gBrowser.selectedBrowser.addEventListener("load", function () { gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); pageInfo = BrowserPageInfo(); - obs.addObserver(observer, "page-info-dialog-loaded", false); + Services.obs.addObserver(observer, "page-info-dialog-loaded", false); }, true); content.location = "https://example.com/browser/browser/base/content/test/feed_tab.html"; @@ -29,7 +27,7 @@ function test() { break; case 2: atTest++; - obs.removeObserver(observer, "page-info-dialog-loaded"); + Services.obs.removeObserver(observer, "page-info-dialog-loaded"); testLockDoubleClick(); break; } @@ -76,9 +74,7 @@ function test() { } function testLockDoubleClick() { - var pageInfoDialogs = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("Browser:page-info"); + var pageInfoDialogs = Services.wm.getEnumerator("Browser:page-info"); var i = 0; while (pageInfoDialogs.hasMoreElements()) { i++; diff --git a/browser/base/content/test/browser_pluginnotification.js b/browser/base/content/test/browser_pluginnotification.js index 606e68e5d718..7c59e4622d33 100644 --- a/browser/base/content/test/browser_pluginnotification.js +++ b/browser/base/content/test/browser_pluginnotification.js @@ -4,8 +4,7 @@ var gTestBrowser = null; var gNextTest = null; function get_test_plugin() { - var ph = Components.classes["@mozilla.org/plugin/host;1"] - .getService(Components.interfaces.nsIPluginHost); + var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); var tags = ph.getPluginTags(); // Find the test plugin @@ -23,9 +22,7 @@ function WindowOpenListener(url, opencallback, closecallback) { this.opencallback = opencallback; this.closecallback = closecallback; - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.addListener(this); + Services.wm.addListener(this); } WindowOpenListener.prototype = { @@ -61,9 +58,7 @@ WindowOpenListener.prototype = { if (this.window != window) return; - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.removeListener(this); + Services.wm.removeListener(this); this.opencallback = null; this.window = null; this.domwindow = null; diff --git a/browser/base/content/test/browser_sanitize-download-history.js b/browser/base/content/test/browser_sanitize-download-history.js index 29af83417d1d..184b966de9a5 100644 --- a/browser/base/content/test/browser_sanitize-download-history.js +++ b/browser/base/content/test/browser_sanitize-download-history.js @@ -71,13 +71,11 @@ function test() let history = doc.getElementById("history-checkbox"); // Add download to DB - let ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); let file = Cc["@mozilla.org/file/directory_service;1"]. getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile); file.append("satitize-dm-test.file"); file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); - let testPath = ios.newFileURI(file).spec; + let testPath = Services.io.newFileURI(file).spec; let data = { name: "381603.patch", source: "https://bugzilla.mozilla.org/attachment.cgi?id=266520", @@ -142,22 +140,20 @@ function test() db.executeSimpleSQL("DELETE FROM moz_downloads"); // Close the UI if necessary - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - let win = ww.getWindowByName("Sanatize", null); + let win = Services.ww.getWindowByName("Sanatize", null); if (win && (win instanceof Ci.nsIDOMWindowInternal)) win.close(); // Start the test when the sanitize window loads - ww.registerNotification(function (aSubject, aTopic, aData) { - ww.unregisterNotification(arguments.callee); + Services.ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.unregisterNotification(arguments.callee); aSubject.QueryInterface(Ci.nsIDOMEventTarget) .addEventListener("DOMContentLoaded", doTest, false); }); // Let the methods that run onload finish before we test let doTest = function() setTimeout(function() { - let win = ww.getWindowByName("Sanitize", null) + let win = Services.ww.getWindowByName("Sanitize", null) .QueryInterface(Ci.nsIDOMWindowInternal); for (let i = 0; i < tests.length; i++) @@ -168,11 +164,11 @@ function test() }, 0); // Show the UI - ww.openWindow(window, - "chrome://browser/content/sanitize.xul", - "Sanitize", - "chrome,titlebar,centerscreen", - null); + Services.ww.openWindow(window, + "chrome://browser/content/sanitize.xul", + "Sanitize", + "chrome,titlebar,centerscreen", + null); waitForExplicitFinish(); } diff --git a/browser/base/content/test/browser_sanitizeDialog.js b/browser/base/content/test/browser_sanitizeDialog.js index 2d0d2531fa69..2b3e86b8a2ae 100644 --- a/browser/base/content/test/browser_sanitizeDialog.js +++ b/browser/base/content/test/browser_sanitizeDialog.js @@ -51,15 +51,13 @@ */ Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://mochikit/content/MochiKit/packed.js"); Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://browser/content/sanitize.js"); -const winWatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); const dm = Cc["@mozilla.org/download-manager;1"]. getService(Ci.nsIDownloadManager); const bhist = Cc["@mozilla.org/browser/global-history;2"]. @@ -540,7 +538,7 @@ WindowHelper.prototype = { if (aTopic != "domwindowopened") return; - winWatch.unregisterNotification(windowObserver); + Services.ww.unregisterNotification(windowObserver); var loaded = false; let win = aSubject.QueryInterface(Ci.nsIDOMWindow); @@ -597,12 +595,12 @@ WindowHelper.prototype = { }); }, false); } - winWatch.registerNotification(windowObserver); - winWatch.openWindow(null, - "chrome://browser/content/sanitize.xul", - "SanitizeDialog", - "chrome,titlebar,dialog,centerscreen,modal", - null); + Services.ww.registerNotification(windowObserver); + Services.ww.openWindow(null, + "chrome://browser/content/sanitize.xul", + "SanitizeDialog", + "chrome,titlebar,dialog,centerscreen,modal", + null); }, /** diff --git a/browser/base/content/test/browser_sanitizeDialog_treeView.js b/browser/base/content/test/browser_sanitizeDialog_treeView.js index 6c023f079d17..5b9be10d6fca 100644 --- a/browser/base/content/test/browser_sanitizeDialog_treeView.js +++ b/browser/base/content/test/browser_sanitizeDialog_treeView.js @@ -50,15 +50,13 @@ */ Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://mochikit/content/MochiKit/packed.js"); Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://browser/content/sanitize.js"); -const winWatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); const dm = Cc["@mozilla.org/download-manager;1"]. getService(Ci.nsIDownloadManager); const bhist = Cc["@mozilla.org/browser/global-history;2"]. @@ -622,7 +620,7 @@ function openWindow(aOnloadCallback) { if (aTopic != "domwindowopened") return; - winWatch.unregisterNotification(windowObserver); + Services.ww.unregisterNotification(windowObserver); let win = aSubject.QueryInterface(Ci.nsIDOMWindow); win.addEventListener("load", function onload(event) { win.removeEventListener("load", onload, false); @@ -641,12 +639,12 @@ function openWindow(aOnloadCallback) { }); }, false); } - winWatch.registerNotification(windowObserver); - winWatch.openWindow(null, - "chrome://browser/content/sanitize.xul", - "Sanitize", - "chrome,titlebar,dialog,centerscreen,modal", - null); + Services.ww.registerNotification(windowObserver); + Services.ww.openWindow(null, + "chrome://browser/content/sanitize.xul", + "Sanitize", + "chrome,titlebar,dialog,centerscreen,modal", + null); } /////////////////////////////////////////////////////////////////////////////// diff --git a/browser/components/places/tests/unit/head_bookmarks.js b/browser/components/places/tests/unit/head_bookmarks.js index cf6674f19155..32447e7c2dfa 100644 --- a/browser/components/places/tests/unit/head_bookmarks.js +++ b/browser/components/places/tests/unit/head_bookmarks.js @@ -37,48 +37,24 @@ * * ***** END LICENSE BLOCK ***** */ -version(170); +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; -const NS_APP_BOOKMARKS_50_FILE = "BMarks"; +Cu.import("resource://gre/modules/Services.jsm"); -var Ci = Components.interfaces; -var Cc = Components.classes; -var Cr = Components.results; - -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +// Import common head. +let (commonFile = do_get_file("../../test_places/head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -var gProfD = do_get_profile(); -var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); +// Put any other stuff relative to this test folder below. -var dirProvider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_BOOKMARKS_50_FILE) { - var bmarks = gProfD.clone(); - bmarks.append("bookmarks.html"); - return bmarks; - } - return null; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(dirProvider); -var XULAppInfo = { +// Needed by some test that relies on having an app registered. +let (XULAppInfo = { vendor: "Mozilla", name: "PlacesTest", ID: "{230de50e-4cd1-11dc-8314-0800200c9a66}", @@ -91,80 +67,29 @@ var XULAppInfo = { OS: "XPCShell", XPCOMABI: "noarch-spidermonkey", - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) || - iid.equals(Ci.nsIXULRuntime) || - iid.equals(Ci.nsISupports)) - return this; - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; - -var XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Cr.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; - -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"), - "XULAppInfo", "@mozilla.org/xre/app-info;1", - XULAppInfoFactory); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIXULAppInfo, + Ci.nsIXULRuntime, + ]) +}) { + let XULAppInfoFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return XULAppInfo.QueryInterface(iid); + } + }; + let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"), + "XULAppInfo", "@mozilla.org/xre/app-info;1", + XULAppInfoFactory); } -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks. - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup. - dump_table("moz_bookmarks"); - dump_table("moz_places"); - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - var cc = root.childCount; - // Dump contents if found. - for (var i = 0; i < cc ; i++) { - var node = root.getChild(i); - print("Found unexpected child at " + i + ": " + node.title); - } - do_check_eq(cc, 0); - root.containerOpen = false; -} - -let gTestDir = do_get_cwd(); const FILENAME_BOOKMARKS_HTML = "bookmarks.html"; -let backup_date = new Date().toLocaleFormat("%Y-%m-%d"); -const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json"; +let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) { + const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json"; +} // Smart bookmarks constants. const SMART_BOOKMARKS_VERSION = 2; @@ -174,179 +99,3 @@ const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator. // Default bookmarks constants. const DEFAULT_BOOKMARKS_ON_TOOLBAR = 2; const DEFAULT_BOOKMARKS_ON_MENU = 3; - -/** - * Creates a bookmarks.html file in the profile folder from a given source file. - * - * @param aFilename - * Name of the file to copy to the profile folder. This file must - * exist in the directory that contains the test files. - * - * @return nsIFile object for the file. - */ -function create_bookmarks_html(aFilename) { - if (!aFilename) - do_throw("you must pass a filename to create_bookmarks_html function"); - remove_bookmarks_html(); - let bookmarksHTMLFile = gTestDir.clone(); - bookmarksHTMLFile.append(aFilename); - do_check_true(bookmarksHTMLFile.exists()); - bookmarksHTMLFile.copyTo(gProfD, FILENAME_BOOKMARKS_HTML); - let profileBookmarksHTMLFile = gProfD.clone(); - profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); - do_check_true(profileBookmarksHTMLFile.exists()); - return profileBookmarksHTMLFile; -} - -/** - * Remove bookmarks.html file from the profile folder. - */ -function remove_bookmarks_html() { - let profileBookmarksHTMLFile = gProfD.clone(); - profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); - if (profileBookmarksHTMLFile.exists()) { - profileBookmarksHTMLFile.remove(false); - do_check_false(profileBookmarksHTMLFile.exists()); - } -} - -/** - * Check bookmarks.html file exists in the profile folder. - * - * @return nsIFile object for the file. - */ -function check_bookmarks_html() { - let profileBookmarksHTMLFile = gProfD.clone(); - profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); - do_check_true(profileBookmarksHTMLFile.exists()); - return profileBookmarksHTMLFile; -} - -/** - * Creates a JSON backup in the profile folder folder from a given source file. - * - * @param aFilename - * Name of the file to copy to the profile folder. This file must - * exist in the directory that contains the test files. - * - * @return nsIFile object for the file. - */ -function create_JSON_backup(aFilename) { - if (!aFilename) - do_throw("you must pass a filename to create_JSON_backup function"); - remove_all_JSON_backups(); - let bookmarksBackupDir = gProfD.clone(); - bookmarksBackupDir.append("bookmarkbackups"); - if (!bookmarksBackupDir.exists()) { - bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); - do_check_true(bookmarksBackupDir.exists()); - } - let bookmarksJSONFile = gTestDir.clone(); - bookmarksJSONFile.append(aFilename); - do_check_true(bookmarksJSONFile.exists()); - bookmarksJSONFile.copyTo(bookmarksBackupDir, FILENAME_BOOKMARKS_JSON); - let profileBookmarksJSONFile = bookmarksBackupDir.clone(); - profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); - do_check_true(profileBookmarksJSONFile.exists()); - return profileBookmarksJSONFile; -} - -/** - * Remove bookmarksbackup dir and all backups from the profile folder. - */ -function remove_all_JSON_backups() { - let bookmarksBackupDir = gProfD.clone(); - bookmarksBackupDir.append("bookmarkbackups"); - if (bookmarksBackupDir.exists()) { - bookmarksBackupDir.remove(true); - do_check_false(bookmarksBackupDir.exists()); - } -} - -/** - * Check a JSON backup file for today exists in the profile folder. - * - * @return nsIFile object for the file. - */ -function check_JSON_backup() { - let profileBookmarksJSONFile = gProfD.clone(); - profileBookmarksJSONFile.append("bookmarkbackups"); - profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); - do_check_true(profileBookmarksJSONFile.exists()); - return profileBookmarksJSONFile; -} - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_browserGlue_smartBookmarks.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} diff --git a/browser/components/places/tests/unit/test_384370.js b/browser/components/places/tests/unit/test_384370.js index 6b94290346b2..2bc13b6c948e 100644 --- a/browser/components/places/tests/unit/test_384370.js +++ b/browser/components/places/tests/unit/test_384370.js @@ -73,7 +73,7 @@ function run_test() { //var bookmarksFileOld = do_get_file("bookmarks.large.html"); var bookmarksFileOld = do_get_file("bookmarks.preplaces.html"); // file pointer to a new places-exported json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.exported.json"); // create bookmarks.exported.json diff --git a/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js b/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js index b7399cbbd0b9..841b68756688 100644 --- a/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js +++ b/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js @@ -90,7 +90,7 @@ function run_test() { stmt.finalize(); // Export bookmarks - var bookmarksFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var bookmarksFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); bookmarksFile.append("bookmarks.exported.html"); if (bookmarksFile.exists()) bookmarksFile.remove(false); diff --git a/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js b/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js index f360f0c59693..8b43edb68cf3 100644 --- a/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js +++ b/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js @@ -115,7 +115,7 @@ var tests = [ data: NSIOBSERVER_DATA_JSON, folderId: null, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { PlacesUtils.restoreBookmarksFromJSONFile(this.file); @@ -169,7 +169,7 @@ var tests = [ data: NSIOBSERVER_DATA_HTML, folderId: null, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { importer.importHTMLFromFile(this.file, false); @@ -223,7 +223,7 @@ var tests = [ data: NSIOBSERVER_DATA_HTML_INIT, folderId: null, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { importer.importHTMLFromFile(this.file, true); @@ -284,7 +284,7 @@ var tests = [ finalTopic: NSIOBSERVER_TOPIC_FAILED, data: NSIOBSERVER_DATA_HTML, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder, "test folder", @@ -407,7 +407,7 @@ function checkBookmarksExist() { * @return The nsILocalFile */ function createFile(aBasename) { - var file = dirSvc.get("ProfD", Ci.nsILocalFile); + var file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); file.append(aBasename); if (file.exists()) file.remove(false); diff --git a/browser/components/places/tests/unit/test_bookmarks_html.js b/browser/components/places/tests/unit/test_bookmarks_html.js index 1c2d94af38c6..2a0922c4f5d8 100644 --- a/browser/components/places/tests/unit/test_bookmarks_html.js +++ b/browser/components/places/tests/unit/test_bookmarks_html.js @@ -104,7 +104,7 @@ function run_test() { // file pointer to legacy bookmarks file var bookmarksFileOld = do_get_file("bookmarks.preplaces.html"); // file pointer to a new places-exported bookmarks file - var bookmarksFileNew = dirSvc.get("ProfD", Ci.nsILocalFile); + var bookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile); bookmarksFileNew.append("bookmarks.exported.html"); // create bookmarks.exported.html diff --git a/browser/components/places/tests/unit/test_browserGlue_distribution.js b/browser/components/places/tests/unit/test_browserGlue_distribution.js index f32857a3f611..e95b61d5aedf 100644 --- a/browser/components/places/tests/unit/test_browserGlue_distribution.js +++ b/browser/components/places/tests/unit/test_browserGlue_distribution.js @@ -47,14 +47,13 @@ const PREF_BMPROCESSED = "distribution.516444.bookmarksProcessed"; const PREF_DISTRIBUTION_ID = "distribution.id"; const TOPIC_FINAL_UI_STARTUP = "final-ui-startup"; -const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete"; const TOPIC_CUSTOMIZATION_COMPLETE = "distribution-customization-complete"; function run_test() { do_test_pending(); // Copy distribution.ini file to our app dir. - let distroDir = dirSvc.get("XCurProcD", Ci.nsIFile); + let distroDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile); distroDir.append("distribution"); let iniFile = distroDir.clone(); iniFile.append("distribution.ini"); @@ -97,13 +96,13 @@ function run_test() { TOPIC_FINAL_UI_STARTUP, null); // Test will continue on customization complete notification. - let observer = { + let cObserver = { observe: function(aSubject, aTopic, aData) { os.removeObserver(this, TOPIC_CUSTOMIZATION_COMPLETE); - continue_test(); + do_execute_soon(continue_test); } } - os.addObserver(observer, TOPIC_CUSTOMIZATION_COMPLETE, false); + os.addObserver(cObserver, TOPIC_CUSTOMIZATION_COMPLETE, false); } } os.addObserver(observer, TOPIC_PLACES_INIT_COMPLETE, false); @@ -145,7 +144,7 @@ function continue_test() { do_register_cleanup(function() { // Remove the distribution file, even if the test failed, otherwise all // next tests will import it. - let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile); + let iniFile = Services.dirsvc.get("XCurProcD", Ci.nsIFile); iniFile.append("distribution"); iniFile.append("distribution.ini"); iniFile.remove(false); diff --git a/browser/components/places/tests/unit/test_browserGlue_prefs.js b/browser/components/places/tests/unit/test_browserGlue_prefs.js index 4dad44c9e625..9a4c668f107d 100644 --- a/browser/components/places/tests/unit/test_browserGlue_prefs.js +++ b/browser/components/places/tests/unit/test_browserGlue_prefs.js @@ -63,8 +63,7 @@ const PREF_IMPORT_BOOKMARKS_HTML = "browser.places.importBookmarksHTML"; const PREF_RESTORE_DEFAULT_BOOKMARKS = "browser.bookmarks.restore_default_bookmarks"; const PREF_SMART_BOOKMARKS_VERSION = "browser.places.smartBookmarksVersion"; const PREF_AUTO_EXPORT_HTML = "browser.bookmarks.autoExportHTML"; -const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete"; -const TOPIC_PLACES_DATABASE_LOCKED = "places-database-locked"; + let tests = []; //------------------------------------------------------------------------------ diff --git a/browser/components/preferences/tests/browser_bug410900.js b/browser/components/preferences/tests/browser_bug410900.js index 043d065608a3..bfb52303de1a 100644 --- a/browser/components/preferences/tests/browser_bug410900.js +++ b/browser/components/preferences/tests/browser_bug410900.js @@ -16,17 +16,14 @@ function test() { getService(Ci.nsIHandlerService); hserv.store(info); - var obs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - function observer(win, topic, data) { if (topic != "app-handler-pane-loaded") return; - obs.removeObserver(observer, "app-handler-pane-loaded"); + Services.obs.removeObserver(observer, "app-handler-pane-loaded"); runTest(win); } - obs.addObserver(observer, "app-handler-pane-loaded", false); + Services.obs.addObserver(observer, "app-handler-pane-loaded", false); openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences", "chrome,titlebar,toolbar,centerscreen,dialog=no", "paneApplications"); diff --git a/browser/components/preferences/tests/privacypane_tests.js b/browser/components/preferences/tests/privacypane_tests.js index 1c20c619271a..eacb712e4355 100644 --- a/browser/components/preferences/tests/privacypane_tests.js +++ b/browser/components/preferences/tests/privacypane_tests.js @@ -36,28 +36,26 @@ * ***** END LICENSE BLOCK ***** */ function runTestOnPrivacyPrefPane(testFunc) { - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); let observer = { observe: function(aSubject, aTopic, aData) { if (aTopic == "domwindowopened") { - ww.unregisterNotification(this); + Services.ww.unregisterNotification(this); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function() { win.removeEventListener("load", arguments.callee, false); testFunc(dialog.document.defaultView); - ww.registerNotification(observer); + Services.ww.registerNotification(observer); dialog.close(); }, false); } else if (aTopic == "domwindowclosed") { - ww.unregisterNotification(this); + Services.ww.unregisterNotification(this); testRunner.runNext(); } } }; - ww.registerNotification(observer); + Services.ww.registerNotification(observer); let dialog = openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences", "chrome,titlebar,toolbar,centerscreen,dialog=no", "panePrivacy"); @@ -528,10 +526,8 @@ function reset_preferences(win) { let testRunner; function run_test_subset(subset) { - let psvc = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); - let instantApplyOrig = psvc.getBoolPref("browser.preferences.instantApply"); - psvc.setBoolPref("browser.preferences.instantApply", true); + let instantApplyOrig = Services.prefs.getBoolPref("browser.preferences.instantApply"); + Services.prefs.setBoolPref("browser.preferences.instantApply", true); waitForExplicitFinish(); @@ -541,7 +537,7 @@ function run_test_subset(subset) { runNext: function() { if (this.counter == this.tests.length) { // cleanup - psvc.setBoolPref("browser.preferences.instantApply", instantApplyOrig); + Services.prefs.setBoolPref("browser.preferences.instantApply", instantApplyOrig); finish(); } else { let self = this; diff --git a/browser/components/privatebrowsing/test/browser/Makefile.in b/browser/components/privatebrowsing/test/browser/Makefile.in index aa98f6b57621..9f6e97751747 100644 --- a/browser/components/privatebrowsing/test/browser/Makefile.in +++ b/browser/components/privatebrowsing/test/browser/Makefile.in @@ -72,6 +72,7 @@ _BROWSER_TEST_FILES = \ browser_privatebrowsing_transition.js \ browser_privatebrowsing_ui.js \ browser_privatebrowsing_urlbarfocus.js \ + browser_privatebrowsing_urlbarundo.js \ browser_privatebrowsing_viewsource.js \ browser_privatebrowsing_windowtitle.js \ browser_privatebrowsing_windowtitle_page.html \ diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js index 401a0e7df7c7..6eab0933918a 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js @@ -57,9 +57,7 @@ function test() { dialogWin.document.documentElement.getButton("cancel").click(); } - Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService) - .addObserver(promptObserver, "common-dialog-loaded", false); + Services.obs.addObserver(promptObserver, "common-dialog-loaded", false); waitForExplicitFinish(); let browser1 = gBrowser.getBrowserForTab(gBrowser.addTab()); @@ -150,9 +148,7 @@ function test() { gBrowser.removeTab(gBrowser.tabContainer.lastChild); gBrowser.removeTab(gBrowser.tabContainer.lastChild); - Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService) - .removeObserver(promptObserver, "common-dialog-loaded", false); + Services.obs.removeObserver(promptObserver, "common-dialog-loaded", false); finish(); } for (let i = 0; i < gBrowser.browsers.length; ++i) diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js index 6db7821af7aa..7ba575a65802 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js @@ -63,10 +63,8 @@ function test() { prefetchCert: true, }; function testCheckbox() { - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { - obsSvc.removeObserver(arguments.callee, "cert-exception-ui-ready", false); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false); ok(win.gCert, "The certificate information should be available now"); let checkbox = win.document.getElementById("permanent"); @@ -90,10 +88,8 @@ function test() { prefetchCert: true, }; function testCheckbox() { - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { - obsSvc.removeObserver(arguments.callee, "cert-exception-ui-ready", false); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false); ok(win.gCert, "The certificate information should be available now"); let checkbox = win.document.getElementById("permanent"); diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js index 873203cfde07..360953b02f94 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js @@ -42,8 +42,6 @@ function test() { // initialization let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); waitForExplicitFinish(); @@ -120,7 +118,7 @@ function test() { function observer(aSubject, aTopic, aData) { isnot(aTopic, "domwindowopened", "The -private-toggle argument should be silent"); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); let tab = gBrowser.selectedTab; let browser = gBrowser.getBrowserForTab(tab); @@ -149,7 +147,7 @@ function test() { let newTab = gBrowser.addTab(); gBrowser.removeTab(tab); - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); finish(); }, true); }, true); diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js index f0d23707d36a..d877a328056e 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js @@ -42,8 +42,6 @@ function test() { // initialization let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); let cp = Cc["@mozilla.org/embedcomp/cookieprompt-service;1"]. getService(Ci.nsICookiePromptService); @@ -54,7 +52,7 @@ function test() { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMWindow); win.addEventListener("load", function onLoad(event) { win.removeEventListener("load", onLoad, false); @@ -76,7 +74,7 @@ function test() { }); }, false); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); let remember = {}; const time = (new Date("Jan 1, 2030")).getTime() / 1000; diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js index 8ec728d14def..f61a601092b3 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js @@ -46,8 +46,6 @@ function test() { getService(Ci.nsIDownloadManager); if (!gDownloadMgr) gDownloadMgr = dm; - let iosvc = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); let panel = document.getElementById("download-monitor"); waitForExplicitFinish(); @@ -159,10 +157,8 @@ function addDownload(dm, aParams) return dl; } -function createURI(aObj) -{ - let ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); +function createURI(aObj) { + let ios = Services.io; return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) : ios.newURI(aObj, null, null); } diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js index 804cd41f7a83..9a610e6ae313 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js @@ -42,8 +42,6 @@ function test() { // initialization let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); waitForExplicitFinish(); // Add a history entry. @@ -59,7 +57,7 @@ function test() { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow); organizer.addEventListener("load", function onLoad(event) { organizer.removeEventListener("load", onLoad, false); @@ -103,12 +101,12 @@ function test() { }, false); } - ww.registerNotification(observer); - ww.openWindow(null, - "chrome://browser/content/places/places.xul", - "", - "chrome,toolbar=yes,dialog=no,resizable", - null); + Services.ww.registerNotification(observer); + Services.ww.openWindow(null, + "chrome://browser/content/places/places.xul", + "", + "chrome,toolbar=yes,dialog=no,resizable", + null); } testForgetThisSiteVisibility(true, function() { diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js index 09e469384cbf..c494f3f9df7c 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js @@ -42,8 +42,6 @@ let cookieManager = Cc["@mozilla.org/cookiemanager;1"]. getService(Ci.nsICookieManager2); let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); -let _obs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); let observerNotified = 0, firstUnloadFired = 0, secondUnloadFired = 0; function pbObserver(aSubject, aTopic, aData) { @@ -56,7 +54,7 @@ function pbObserver(aSubject, aTopic, aData) { is(firstUnloadFired, 1, "The first unload event should have been processed by now"); break; case "exit": - _obs.removeObserver(pbObserver, "private-browsing"); + Services.obs.removeObserver(pbObserver, "private-browsing"); observerNotified++; is(observerNotified, 2, "This should be the second notification"); is(secondUnloadFired, 1, "The second unload event should have been processed by now"); @@ -66,7 +64,7 @@ function pbObserver(aSubject, aTopic, aData) { function test() { waitForExplicitFinish(); - _obs.addObserver(pbObserver, "private-browsing", false); + Services.obs.addObserver(pbObserver, "private-browsing", false); is(gBrowser.tabs.length, 1, "There should only be one tab"); let testTab = gBrowser.addTab(); gBrowser.selectedTab = testTab; diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js index bc439e726e49..d210dac2a958 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js @@ -48,9 +48,7 @@ function test() { if (aTopic == "private-browsing") observerData = aData; } - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.addObserver(observer, "private-browsing", false); + Services.obs.addObserver(observer, "private-browsing", false); let pbMenuItem = document.getElementById("privateBrowsingItem"); // add a new blank tab to ensure the title can be meaningfully compared later gBrowser.selectedTab = gBrowser.addTab(); @@ -92,6 +90,6 @@ function test() { // cleanup gBrowser.removeCurrentTab(); - os.removeObserver(observer, "private-browsing"); + Services.obs.removeObserver(observer, "private-browsing"); gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session"); } diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js new file mode 100644 index 000000000000..acf1581b5801 --- /dev/null +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js @@ -0,0 +1,64 @@ +/* ***** 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 Private Browsing Tests. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ehsan Akhgari (Original Author) + * + * 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 ***** */ + +// This test makes sure that the undo history of the URL bar is cleared when +// leaving the private browsing mode. + +function test() { + // initialization + Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true); + let pb = Cc["@mozilla.org/privatebrowsing;1"]. + getService(Ci.nsIPrivateBrowsingService); + + // enter private browsing mode + pb.privateBrowsingEnabled = true; + + // fill in the URL bar with something + gURLBar.value = "some test value"; + + ok(gURLBar.editor.transactionManager.numberOfUndoItems > 0, + "The undo history for the URL bar should not be empty"); + + // leave private browsing mode + pb.privateBrowsingEnabled = false; + + is(gURLBar.editor.transactionManager.numberOfUndoItems, 0, + "The undo history of the URL bar should be cleared after leaving the private browsing mode"); + + // cleanup + Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session"); +} + diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js index 9e5b1350af4e..c6d6b3504f3f 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js @@ -50,13 +50,11 @@ function test() { aboutBrowser.addEventListener("load", function () { aboutBrowser.removeEventListener("load", arguments.callee, true); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); function observer(aSubject, aTopic, aData) { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function () { @@ -71,7 +69,7 @@ function test() { }, true); }, false); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); openViewSource(); @@ -84,14 +82,14 @@ function test() { function observer(aSubject, aTopic, aData) { if (aTopic == "domwindowclosed") { ok(true, "Entering the private browsing mode should close the view source window"); - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); step2(); } else if (aTopic == "domwindowopened") ok(false, "Entering the private browsing mode should not open any view source window"); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); gBrowser.addTabsProgressListener({ onLocationChange: function() {}, @@ -124,7 +122,7 @@ function test() { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function () { @@ -139,7 +137,7 @@ function test() { }, true); }, false); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); openViewSource(); } @@ -151,12 +149,12 @@ function test() { if (aTopic == "domwindowclosed") { ok(true, "Leaving the private browsing mode should close the existing view source window"); if (++events == 2) - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); } else if (aTopic == "domwindowopened") { ok(true, "Leaving the private browsing mode should restore the previous view source window"); if (++events == 2) - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function () { @@ -177,7 +175,7 @@ function test() { }, false); } } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); // exit private browsing mode pb.privateBrowsingEnabled = false; diff --git a/browser/components/search/test/browser_415700.js b/browser/components/search/test/browser_415700.js index 44c872aa95df..a5899e749918 100644 --- a/browser/components/search/test/browser_415700.js +++ b/browser/components/search/test/browser_415700.js @@ -33,10 +33,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -var gSS = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); -var gObs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); +var gSS = Services.search; function observers(aSubject, aTopic, aData) { switch (aData) { @@ -54,7 +51,7 @@ function observers(aSubject, aTopic, aData) { function test() { waitForExplicitFinish(); - gObs.addObserver(observers, "browser-search-engine-modified", false); + Services.obs.addObserver(observers, "browser-search-engine-modified", false); gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml", Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC", @@ -83,6 +80,6 @@ function test4() { ok(engine, "An engine is present."); isnot(engine.name, "Foo", "Current engine reset after removal"); - gObs.removeObserver(observers, "browser-search-engine-modified"); + Services.obs.removeObserver(observers, "browser-search-engine-modified"); finish(); } diff --git a/browser/components/search/test/browser_426329.js b/browser/components/search/test/browser_426329.js index 8d38693623a5..2cab4518fccf 100644 --- a/browser/components/search/test/browser_426329.js +++ b/browser/components/search/test/browser_426329.js @@ -8,10 +8,7 @@ function test() { searchBar.value = "test"; - var obs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - var ss = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); + var ss = Services.search; function observer(aSub, aTopic, aData) { switch (aData) { @@ -26,13 +23,13 @@ function test() { testReturn(); break; case "engine-removed": - obs.removeObserver(observer, "browser-search-engine-modified"); + Services.obs.removeObserver(observer, "browser-search-engine-modified"); finish(); break; } } - obs.addObserver(observer, "browser-search-engine-modified", false); + Services.obs.addObserver(observer, "browser-search-engine-modified", false); ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml", Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00", false); diff --git a/browser/components/search/test/browser_483086.js b/browser/components/search/test/browser_483086.js index f449ebe73228..536a0e5ff577 100644 --- a/browser/components/search/test/browser_483086.js +++ b/browser/components/search/test/browser_483086.js @@ -33,8 +33,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -let gSS = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); +let gSS = Services.search; let gObs = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); @@ -51,13 +50,13 @@ function test() { gSS.removeEngine(engine); break; case "engine-removed": - gObs.removeObserver(observer, "browser-search-engine-modified"); + Services.obs.removeObserver(observer, "browser-search-engine-modified"); test2(); break; } } - gObs.addObserver(observer, "browser-search-engine-modified", false); + Services.obs.addObserver(observer, "browser-search-engine-modified", false); gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-1.xml", Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00", false); @@ -73,13 +72,13 @@ function test2() { gSS.removeEngine(engine); break; case "engine-removed": - gObs.removeObserver(observer, "browser-search-engine-modified"); + Services.obs.removeObserver(observer, "browser-search-engine-modified"); finish(); break; } } - gObs.addObserver(observer, "browser-search-engine-modified", false); + Services.obs.addObserver(observer, "browser-search-engine-modified", false); gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-2.xml", Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00", false); diff --git a/browser/components/sessionstore/test/browser/browser_248970_a.js b/browser/components/sessionstore/test/browser/browser_248970_a.js index 4937d07694be..0184d804be7c 100644 --- a/browser/components/sessionstore/test/browser/browser_248970_a.js +++ b/browser/components/sessionstore/test/browser/browser_248970_a.js @@ -63,13 +63,11 @@ function test() { return -1; } - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); function waitForFileExistence(aMessage, aDoNext) { const TOPIC = "sessionstore-state-write-complete"; - os.addObserver(function (aSubject, aTopic, aData) { + Services.obs.addObserver(function (aSubject, aTopic, aData) { // Remove the observer so we do not leak. - os.removeObserver(arguments.callee, TOPIC); + Services.obs.removeObserver(arguments.callee, TOPIC); // Check that the file exists. ok(getSessionstoreFile().exists(), aMessage); diff --git a/browser/components/sessionstore/test/browser/browser_354894.js b/browser/components/sessionstore/test/browser/browser_354894.js index 46d761554089..1107d64582bf 100644 --- a/browser/components/sessionstore/test/browser/browser_354894.js +++ b/browser/components/sessionstore/test/browser/browser_354894.js @@ -109,9 +109,7 @@ function browserWindowsCount(expected, msg) { if (typeof expected == "number") expected = [expected, expected]; let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -172,8 +170,6 @@ function test() { aCancel.QueryInterface(Ci.nsISupportsPRBool).data = true; } } - let observerService = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); /** * Helper: Sets prefs as the testsuite requires @@ -194,7 +190,7 @@ function test() { function setupTestsuite(testFn) { // Register our observers for (let o in observing) - observerService.addObserver(observer, o, false); + Services.obs.addObserver(observer, o, false); // Make the main test window not count as a browser window any longer oldWinType = document.documentElement.getAttribute("windowtype"); @@ -207,7 +203,7 @@ function test() { function cleanupTestsuite(callback) { // Finally remove observers again for (let o in observing) - observerService.removeObserver(observer, o, false); + Services.obs.removeObserver(observer, o, false); // Reset the prefs we touched [ diff --git a/browser/components/sessionstore/test/browser/browser_394759.js b/browser/components/sessionstore/test/browser/browser_394759.js index 37938c9b75bb..9c7ed76da23f 100644 --- a/browser/components/sessionstore/test/browser/browser_394759.js +++ b/browser/components/sessionstore/test/browser/browser_394759.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js b/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js index eb95a62294fb..ef42f42c414c 100644 --- a/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js +++ b/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js @@ -39,9 +39,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -74,10 +72,8 @@ function test() { // Wait for the sessionstore.js file to be written before going on. // Note: we don't wait for the complete event, since if asyncCopy fails we // would timeout. - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.addObserver(function (aSubject, aTopic, aData) { - os.removeObserver(arguments.callee, aTopic); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, aTopic); info("sessionstore.js is being written"); executeSoon(continue_test); }, "sessionstore-state-write", false); diff --git a/browser/components/sessionstore/test/browser/browser_423132.js b/browser/components/sessionstore/test/browser/browser_423132.js index 3f33eff14dd2..253b24bec0b2 100644 --- a/browser/components/sessionstore/test/browser/browser_423132.js +++ b/browser/components/sessionstore/test/browser/browser_423132.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_448741.js b/browser/components/sessionstore/test/browser/browser_448741.js index 88d0bfd66dfc..5d2548222757 100644 --- a/browser/components/sessionstore/test/browser/browser_448741.js +++ b/browser/components/sessionstore/test/browser/browser_448741.js @@ -39,7 +39,6 @@ function test() { // test setup let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); waitForExplicitFinish(); let uniqueName = "bug 448741"; @@ -71,7 +70,7 @@ function test() { ok(valueWasCleaned, "found and removed the specific tab value"); aSubject.data = uneval(state); - os.removeObserver(cleaningObserver, aTopic, false); + Services.obs.removeObserver(cleaningObserver, aTopic, false); } // make sure that all later observers don't see that value any longer @@ -82,15 +81,15 @@ function test() { // clean up gBrowser.removeTab(tab); - os.removeObserver(checkingObserver, aTopic, false); + Services.obs.removeObserver(checkingObserver, aTopic, false); if (gPrefService.prefHasUserValue("browser.sessionstore.interval")) gPrefService.clearUserPref("browser.sessionstore.interval"); finish(); } // last added observers are invoked first - os.addObserver(checkingObserver, "sessionstore-state-write", false); - os.addObserver(cleaningObserver, "sessionstore-state-write", false); + Services.obs.addObserver(checkingObserver, "sessionstore-state-write", false); + Services.obs.addObserver(cleaningObserver, "sessionstore-state-write", false); // trigger an immediate save operation gPrefService.setIntPref("browser.sessionstore.interval", 0); diff --git a/browser/components/sessionstore/test/browser/browser_461634.js b/browser/components/sessionstore/test/browser/browser_461634.js index 512ee8ab7383..0e2f15db818f 100644 --- a/browser/components/sessionstore/test/browser/browser_461634.js +++ b/browser/components/sessionstore/test/browser/browser_461634.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_464199.js b/browser/components/sessionstore/test/browser/browser_464199.js index ddc0e0cf9566..60575c448c23 100644 --- a/browser/components/sessionstore/test/browser/browser_464199.js +++ b/browser/components/sessionstore/test/browser/browser_464199.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_465223.js b/browser/components/sessionstore/test/browser/browser_465223.js index bc388534978a..6e39b20debcf 100644 --- a/browser/components/sessionstore/test/browser/browser_465223.js +++ b/browser/components/sessionstore/test/browser/browser_465223.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_477657.js b/browser/components/sessionstore/test/browser/browser_477657.js index 1efae3bb6182..68b4f3e1fe07 100644 --- a/browser/components/sessionstore/test/browser/browser_477657.js +++ b/browser/components/sessionstore/test/browser/browser_477657.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_480148.js b/browser/components/sessionstore/test/browser/browser_480148.js index d6705c8b9ddf..18f7abcc025d 100644 --- a/browser/components/sessionstore/test/browser/browser_480148.js +++ b/browser/components/sessionstore/test/browser/browser_480148.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_490040.js b/browser/components/sessionstore/test/browser/browser_490040.js index 9ea372e7b24a..bdfdb8f214a2 100644 --- a/browser/components/sessionstore/test/browser/browser_490040.js +++ b/browser/components/sessionstore/test/browser/browser_490040.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -53,10 +51,6 @@ function test() { let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); waitForExplicitFinish(); @@ -98,7 +92,7 @@ function test() { break; case "domwindowclosed": - ww.unregisterNotification(windowObserver); + Services.ww.unregisterNotification(windowObserver); // Use executeSoon to ensure this happens after SS observer. executeSoon(function () { is(ss.getClosedWindowCount(), @@ -110,12 +104,12 @@ function test() { break; } } - ww.registerNotification(windowObserver); - ww.openWindow(null, - location, - "_blank", - "chrome,all,dialog=no", - null); + Services.ww.registerNotification(windowObserver); + Services.ww.openWindow(null, + location, + "_blank", + "chrome,all,dialog=no", + null); } // Only windows with open tabs are restorable. Windows where a lone tab is diff --git a/browser/components/sessionstore/test/browser/browser_491168.js b/browser/components/sessionstore/test/browser/browser_491168.js index 91ecdef7a59b..6acb929b5a6f 100644 --- a/browser/components/sessionstore/test/browser/browser_491168.js +++ b/browser/components/sessionstore/test/browser/browser_491168.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -52,7 +50,6 @@ function test() { // test setup let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); waitForExplicitFinish(); @@ -91,6 +88,6 @@ function test() { }, true); },true); - let referrerURI = ioService.newURI(REFERRER1, null, null); + let referrerURI = Services.io.newURI(REFERRER1, null, null); browser.loadURI("http://example.org", referrerURI, null); } diff --git a/browser/components/sessionstore/test/browser/browser_491577.js b/browser/components/sessionstore/test/browser/browser_491577.js index b068c7f17a6c..40fcd2925bc8 100644 --- a/browser/components/sessionstore/test/browser/browser_491577.js +++ b/browser/components/sessionstore/test/browser/browser_491577.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_493467.js b/browser/components/sessionstore/test/browser/browser_493467.js index 5359f243cecb..6b5fcdb9b644 100644 --- a/browser/components/sessionstore/test/browser/browser_493467.js +++ b/browser/components/sessionstore/test/browser/browser_493467.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_495495.js b/browser/components/sessionstore/test/browser/browser_495495.js index 7c2faaadd1d2..6c7bacb0c4e0 100644 --- a/browser/components/sessionstore/test/browser/browser_495495.js +++ b/browser/components/sessionstore/test/browser/browser_495495.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_514751.js b/browser/components/sessionstore/test/browser/browser_514751.js index 015d1b5b755b..4d740af206fa 100644 --- a/browser/components/sessionstore/test/browser/browser_514751.js +++ b/browser/components/sessionstore/test/browser/browser_514751.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_522545.js b/browser/components/sessionstore/test/browser/browser_522545.js index 53f619663f47..99247d2dc334 100644 --- a/browser/components/sessionstore/test/browser/browser_522545.js +++ b/browser/components/sessionstore/test/browser/browser_522545.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_524745.js b/browser/components/sessionstore/test/browser/browser_524745.js index d2dfe57b2e1d..0d10c7998ac4 100644 --- a/browser/components/sessionstore/test/browser/browser_524745.js +++ b/browser/components/sessionstore/test/browser/browser_524745.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -53,8 +51,6 @@ function test() { let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); let uniqKey = "bug524745"; let uniqVal = Date.now(); diff --git a/browser/components/sessionstore/test/browser/browser_526613.js b/browser/components/sessionstore/test/browser/browser_526613.js index 095136474223..2014c63047d7 100644 --- a/browser/components/sessionstore/test/browser/browser_526613.js +++ b/browser/components/sessionstore/test/browser/browser_526613.js @@ -41,15 +41,11 @@ function test() { // test setup let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); waitForExplicitFinish(); function browserWindowsCount(expected) { let count = 0; - let e = wm.getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -87,7 +83,7 @@ function test() { // let the first window be focused (see above) function pollMostRecentWindow() { - if (wm.getMostRecentWindow("navigator:browser") == window) { + if (Services.wm.getMostRecentWindow("navigator:browser") == window) { ss.setBrowserState(oldState); } else { info("waiting for the current window to become active"); @@ -100,11 +96,11 @@ function test() { else { browserWindowsCount(1); ok(!window.closed, "Restoring the old state should have left this window open"); - os.removeObserver(observer, "sessionstore-browser-state-restored"); + Services.obs.removeObserver(observer, "sessionstore-browser-state-restored"); finish(); } } - os.addObserver(observer, "sessionstore-browser-state-restored", false); + Services.obs.addObserver(observer, "sessionstore-browser-state-restored", false); // set browser to test state ss.setBrowserState(JSON.stringify(testState)); diff --git a/browser/components/sessionstore/test/browser/browser_528776.js b/browser/components/sessionstore/test/browser/browser_528776.js index 5b4d169003bf..5534a69a981b 100644 --- a/browser/components/sessionstore/test/browser/browser_528776.js +++ b/browser/components/sessionstore/test/browser/browser_528776.js @@ -1,9 +1,8 @@ var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); -var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); function browserWindowsCount(expected) { var count = 0; - var e = wm.getEnumerator("navigator:browser"); + var e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/wintaskbar/WindowsPreviewPerTab.jsm b/browser/components/wintaskbar/WindowsPreviewPerTab.jsm index 1bffc98e1047..9e1ea1501a34 100644 --- a/browser/components/wintaskbar/WindowsPreviewPerTab.jsm +++ b/browser/components/wintaskbar/WindowsPreviewPerTab.jsm @@ -180,6 +180,12 @@ PreviewController.prototype = { this.linkedBrowser.removeEventListener("pageshow", this, false); this.linkedBrowser.removeEventListener("DOMTitleChanged", this, false); this.linkedBrowser.removeEventListener("MozAfterPaint", this, false); + + // Break cycles, otherwise we end up leaking the window with everything + // attached to it. + delete this.win; + delete this.preview; + delete this.dirtyRegion; }, get wrappedJSObject() { return this; @@ -383,7 +389,6 @@ function TabWindow(win) { this.tabbrowser.tabContainer.addEventListener(this.events[i], this, false); this.tabbrowser.addTabsProgressListener(this); - AeroPeek.windows.push(this); let tabs = this.tabbrowser.tabs; for (let i = 0; i < tabs.length; i++) @@ -402,6 +407,8 @@ TabWindow.prototype = { let tabs = this.tabbrowser.tabs; + this.tabbrowser.removeTabsProgressListener(this); + for (let i = 0; i < this.events.length; i++) this.tabbrowser.tabContainer.removeEventListener(this.events[i], this, false); @@ -589,6 +596,17 @@ var AeroPeek = { this.enabled = this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME); }, + destroy: function destroy() { + this._enabled = false; + + this.prefs.removeObserver(TOGGLE_PREF_NAME, this); + this.prefs.removeObserver(DISABLE_THRESHOLD_PREF_NAME, this); + this.prefs.removeObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this); + + if (this.cacheTimer) + this.cacheTimer.cancel(); + }, + get enabled() { return this._enabled; }, @@ -636,7 +654,10 @@ var AeroPeek = { return; win.gTaskbarTabGroup.destroy(); - win.gTaskbarTabGroup = null; + delete win.gTaskbarTabGroup; + + if (this.windows.length == 0) + this.destroy(); }, resetCacheTimer: function () { diff --git a/browser/fuel/test/browser_Application.js b/browser/fuel/test/browser_Application.js index 25d5a8408567..e7b0074243ce 100644 --- a/browser/fuel/test/browser_Application.js +++ b/browser/fuel/test/browser_Application.js @@ -1,6 +1,3 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - // This listens for the next opened window and checks it is of the right url. // opencallback is called when the new window is fully loaded // closecallback is called when the window is closed @@ -9,9 +6,7 @@ function WindowOpenListener(url, opencallback, closecallback) { this.opencallback = opencallback; this.closecallback = closecallback; - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - wm.addListener(this); + Services.wm.addListener(this); } WindowOpenListener.prototype = { @@ -47,9 +42,7 @@ WindowOpenListener.prototype = { if (this.window != window) return; - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - wm.removeListener(this); + Services.wm.removeListener(this); this.opencallback = null; this.window = null; this.domwindow = null; diff --git a/browser/fuel/test/browser_ApplicationQuitting.js b/browser/fuel/test/browser_ApplicationQuitting.js index f709cc128cf1..520acfb6dbd1 100644 --- a/browser/fuel/test/browser_ApplicationQuitting.js +++ b/browser/fuel/test/browser_ApplicationQuitting.js @@ -5,14 +5,13 @@ function test() { "Received a quit request we're going to deny"); aSubject.data = true; } - + // ensure that we don't accidentally quit - let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.addObserver(quitRequestObserver, "quit-application-requested", false); - + Services.obs.addObserver(quitRequestObserver, "quit-application-requested", false); + ok(!Application.quit(), "Tried to quit - and didn't succeed"); ok(!Application.restart(), "Tried to restart - and didn't succeed"); - + // clean up - os.removeObserver(quitRequestObserver, "quit-application-requested", false); + Services.obs.removeObserver(quitRequestObserver, "quit-application-requested", false); } diff --git a/browser/fuel/test/browser_Bookmarks.js b/browser/fuel/test/browser_Bookmarks.js index fd71f2fcfa56..552c9572b7df 100644 --- a/browser/fuel/test/browser_Bookmarks.js +++ b/browser/fuel/test/browser_Bookmarks.js @@ -1,12 +1,8 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - var gLastFolderAction = ""; var gLastBookmarkAction = ""; function url(spec) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return ios.newURI(spec, null, null); + return Services.io.newURI(spec, null, null); } function test() { diff --git a/configure.in b/configure.in index a1fd0aa820f3..80633491e2cb 100644 --- a/configure.in +++ b/configure.in @@ -132,7 +132,7 @@ GCONF_VERSION=1.2.1 GIO_VERSION=2.0 STARTUP_NOTIFICATION_VERSION=0.8 DBUS_VERSION=0.60 -SQLITE_VERSION=3.6.23 +SQLITE_VERSION=3.6.23.1 LIBNOTIFY_VERSION=0.4 MSMANIFEST_TOOL= @@ -6595,6 +6595,13 @@ if test $MOZ_PLATFORM_MAEMO; then if test -z "$_LIB_FOUND"; then AC_MSG_ERROR([Hildon FM-2 is required when building for Maemo]) fi + + PKG_CHECK_MODULES(LIBLOCATION,liblocation, _LIB_FOUND=1, _LIB_FOUND=) + MOZ_PLATFORM_MAEMO_LIBS="$MOZ_PLATFORM_MAEMO_LIBS $LIBLOCATION_LIBS" + MOZ_PLATFORM_MAEMO_CFLAGS="$MOZ_PLATFORM_MAEMO_CFLAGS $LIBLOCATION_CFLAGS" + if test -z "$_LIB_FOUND"; then + AC_MSG_ERROR([liblocation is required when building for Maemo]) + fi fi AC_SUBST(MOZ_PLATFORM_MAEMO_LIBS) diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index abde159d3ffa..a9da0ce1a1b9 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -310,12 +310,12 @@ nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *v if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) return JS_FALSE; - if (argc < 7 || (argc > 7 && argc < 9)) + if (argc < 7) return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); jsval *argv = JS_ARGV(cx, vp); - int32 intargs[8]; + int32 intargs[9]; // convert the first six args, they must be ints for (jsuint i = 0; i < 6; ++i) { diff --git a/content/events/src/nsContentEventHandler.cpp b/content/events/src/nsContentEventHandler.cpp index 0f545985d9af..bfb031e32935 100644 --- a/content/events/src/nsContentEventHandler.cpp +++ b/content/events/src/nsContentEventHandler.cpp @@ -788,7 +788,10 @@ nsContentEventHandler::OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent) nsLayoutUtils::GetEventCoordinatesRelativeTo(&eventOnRoot, rootFrame); nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot); - if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame) { + if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame || + !targetFrame->GetContent() || + !nsContentUtils::ContentIsDescendantOf(targetFrame->GetContent(), + mRootContent)) { // there is no character at the point. aEvent->mReply.mOffset = nsQueryContentEvent::NOT_FOUND; aEvent->mSucceeded = PR_TRUE; diff --git a/content/html/content/public/nsHTMLAudioElement.h b/content/html/content/public/nsHTMLAudioElement.h index 59ef12943b43..baf65833079e 100644 --- a/content/html/content/public/nsHTMLAudioElement.h +++ b/content/html/content/public/nsHTMLAudioElement.h @@ -35,6 +35,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#if !defined(nsHTMLAudioElement_h__) +#define nsHTMLAudioElement_h__ + #include "nsIDOMHTMLAudioElement.h" #include "nsIJSNativeInitializer.h" #include "nsHTMLMediaElement.h" @@ -74,3 +77,5 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; }; + +#endif diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 7be197a982ec..b78e7bac2f86 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -35,6 +35,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#if !defined(nsHTMLMediaElement_h__) +#define nsHTMLMediaElement_h__ + #include "nsIDOMHTMLMediaElement.h" #include "nsGenericHTMLElement.h" #include "nsMediaDecoder.h" @@ -538,3 +541,5 @@ protected: nsRefPtr mPrintSurface; }; + +#endif diff --git a/content/html/content/public/nsHTMLVideoElement.h b/content/html/content/public/nsHTMLVideoElement.h index b6d6ad7e3cd3..c32861569b36 100644 --- a/content/html/content/public/nsHTMLVideoElement.h +++ b/content/html/content/public/nsHTMLVideoElement.h @@ -35,6 +35,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#if !defined(nsHTMLVideoElement_h__) +#define nsHTMLVideoElement_h__ + #include "nsIDOMHTMLVideoElement.h" #include "nsHTMLMediaElement.h" @@ -76,3 +79,5 @@ public: // If there is no video frame, returns the given default size. nsIntSize GetVideoSize(nsIntSize defaultSize); }; + +#endif diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 4777a95d213c..97165ac43a6a 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -84,6 +84,7 @@ #include "nsLayoutUtils.h" #include "nsVideoFrame.h" #include "BasicLayers.h" +#include #ifdef MOZ_OGG #include "nsOggDecoder.h" @@ -819,7 +820,7 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCurrentTime(float aCurrentTime) /* readonly attribute float duration; */ NS_IMETHODIMP nsHTMLMediaElement::GetDuration(float *aDuration) { - *aDuration = mDecoder ? mDecoder->GetDuration() : 0.0; + *aDuration = mDecoder ? mDecoder->GetDuration() : std::numeric_limits::quiet_NaN(); return NS_OK; } diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 29b288ee64ff..5a78fd11259d 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1849,7 +1849,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) if (!IsHTML() || mDisableDocWrite) { // No calling document.open() on XHTML - return NS_ERROR_DOM_INVALID_ACCESS_ERR; + return NS_ERROR_DOM_INVALID_STATE_ERR; } PRBool loadAsHtml5 = nsHtml5Module::sEnabled; @@ -2099,7 +2099,7 @@ nsHTMLDocument::Close() if (!IsHTML()) { // No calling document.close() on XHTML! - return NS_ERROR_DOM_INVALID_ACCESS_ERR; + return NS_ERROR_DOM_INVALID_STATE_ERR; } nsresult rv = NS_OK; @@ -2164,7 +2164,7 @@ nsHTMLDocument::WriteCommon(const nsAString& aText, if (!IsHTML() || mDisableDocWrite) { // No calling document.write*() on XHTML! - return NS_ERROR_DOM_INVALID_ACCESS_ERR; + return NS_ERROR_DOM_INVALID_STATE_ERR; } nsresult rv = NS_OK; diff --git a/content/html/document/src/nsHTMLFragmentContentSink.cpp b/content/html/document/src/nsHTMLFragmentContentSink.cpp index 21f0971ce3c4..7cddd9dc934e 100644 --- a/content/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp @@ -134,7 +134,6 @@ public: nsIContent* aContent); nsresult AddText(const nsAString& aString); - nsresult AddTextToContent(nsIContent* aContent, const nsAString& aText); nsresult FlushText(); void ProcessBaseTag(nsIContent* aContent); @@ -763,26 +762,6 @@ nsHTMLFragmentContentSink::AddText(const nsAString& aString) return NS_OK; } -nsresult -nsHTMLFragmentContentSink::AddTextToContent(nsIContent* aContent, const nsAString& aText) { - NS_ASSERTION(aContent !=nsnull, "can't add text w/o a content"); - - nsresult result=NS_OK; - - if(aContent) { - if (!aText.IsEmpty()) { - nsCOMPtr text; - result = NS_NewTextNode(getter_AddRefs(text), mNodeInfoManager); - if (NS_SUCCEEDED(result)) { - text->SetText(aText, PR_TRUE); - - result = aContent->AppendChildTo(text, PR_FALSE); - } - } - } - return result; -} - nsresult nsHTMLFragmentContentSink::FlushText() { diff --git a/content/html/document/test/test_bug332848.xhtml b/content/html/document/test/test_bug332848.xhtml index f8f824d60cf7..0cbdf327b1ed 100644 --- a/content/html/document/test/test_bug332848.xhtml +++ b/content/html/document/test/test_bug332848.xhtml @@ -28,7 +28,7 @@ function test() { document.open(); is(0, 1, "document.open succeeded"); } catch (e) { - is (e.code, DOMException.INVALID_ACCESS_ERR, + is (e.code, DOMException.INVALID_STATE_ERR, "Wrong exception from document.open"); } @@ -36,7 +36,15 @@ function test() { document.write("aaa"); is(0, 1, "document.write succeeded"); } catch (e) { - is (e.code, DOMException.INVALID_ACCESS_ERR, + is (e.code, DOMException.INVALID_STATE_ERR, + "Wrong exception from document.write"); + } + + try { + document.writeln("aaa"); + is(0, 1, "document.write succeeded"); + } catch (e) { + is (e.code, DOMException.INVALID_STATE_ERR, "Wrong exception from document.write"); } @@ -44,7 +52,7 @@ function test() { document.close(); is(0, 1, "document.close succeeded"); } catch (e) { - is (e.code, DOMException.INVALID_ACCESS_ERR, + is (e.code, DOMException.INVALID_STATE_ERR, "Wrong exception from document.close"); } } diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 0d237c4c0e41..12452f7d51ec 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -45,6 +45,9 @@ extern "C" { #include "sydneyaudio/sydney_audio.h" } +#include "mozilla/TimeStamp.h" + +using mozilla::TimeStamp; #ifdef PR_LOGGING PRLogModuleInfo* gAudioStreamLog = nsnull; @@ -68,7 +71,8 @@ nsAudioStream::nsAudioStream() : mAudioHandle(0), mRate(0), mChannels(0), - mFormat(FORMAT_S16_LE) + mFormat(FORMAT_S16_LE), + mPaused(PR_FALSE) { } @@ -110,13 +114,14 @@ void nsAudioStream::Shutdown() mAudioHandle = nsnull; } -void nsAudioStream::Write(const void* aBuf, PRUint32 aCount) +void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) { NS_ABORT_IF_FALSE(aCount % mChannels == 0, "Buffer size must be divisible by channel count"); + NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block"); PRUint32 offset = mBufferOverflow.Length(); - PRInt32 count = aCount + offset; + PRUint32 count = aCount + offset; if (!mAudioHandle) return; @@ -168,21 +173,28 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount) } } - PRInt32 available = Available(); - if (available < count) { - mBufferOverflow.AppendElements(s_data.get() + available, (count - available)); - count = available; + if (!aBlocking) { + // We're running in non-blocking mode, crop the data to the amount + // which is available in the audio buffer, and save the rest for + // subsequent calls. + PRUint32 available = Available(); + if (available < count) { + mBufferOverflow.AppendElements(s_data.get() + available, (count - available)); + count = available; + } } if (sa_stream_write(static_cast(mAudioHandle), - s_data.get(), count * sizeof(short)) != SA_SUCCESS) { + s_data.get(), + count * sizeof(short)) != SA_SUCCESS) + { PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error")); Shutdown(); } } } -PRInt32 nsAudioStream::Available() +PRUint32 nsAudioStream::Available() { // If the audio backend failed to open, lie and say we'll accept some // data. @@ -225,7 +237,7 @@ void nsAudioStream::Pause() { if (!mAudioHandle) return; - + mPaused = PR_TRUE; sa_stream_pause(static_cast(mAudioHandle)); } @@ -233,14 +245,14 @@ void nsAudioStream::Resume() { if (!mAudioHandle) return; - + mPaused = PR_FALSE; sa_stream_resume(static_cast(mAudioHandle)); } -float nsAudioStream::GetPosition() +PRInt64 nsAudioStream::GetPosition() { if (!mAudioHandle) - return -1.0; + return -1; sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE; #if defined(XP_WIN) @@ -249,9 +261,9 @@ float nsAudioStream::GetPosition() PRInt64 position = 0; if (sa_stream_get_position(static_cast(mAudioHandle), positionType, &position) == SA_SUCCESS) { - return (position / float(mRate) / mChannels / sizeof(short)); + return ((1000 * position) / mRate / mChannels / sizeof(short)); } - return -1.0; + return -1; } diff --git a/content/media/nsAudioStream.h b/content/media/nsAudioStream.h index 5ba06b31419d..a054e67f7af4 100644 --- a/content/media/nsAudioStream.h +++ b/content/media/nsAudioStream.h @@ -76,11 +76,14 @@ class nsAudioStream // Write sound data to the audio hardware. aBuf is an array of samples in // the format specified by mFormat of length aCount. aCount should be // evenly divisible by the number of channels in this audio stream. - void Write(const void* aBuf, PRUint32 aCount); + // When aBlocking is PR_TRUE, we'll block until the write has completed, + // otherwise we'll buffer any data we can't write immediately, and write + // it in a later call. + void Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking); // Return the number of sound samples that can be written to the audio device // without blocking. - PRInt32 Available(); + PRUint32 Available(); // Set the current volume of the audio playback. This is a value from // 0 (meaning muted) to 1 (meaning full volume). @@ -95,9 +98,12 @@ class nsAudioStream // Resume audio playback void Resume(); - // Return the position in seconds of the sample being played by the + // Return the position in milliseconds of the sample being played by the // audio hardware. - float GetPosition(); + PRInt64 GetPosition(); + + // Returns PR_TRUE when the audio stream is paused. + PRBool IsPaused() { return mPaused; } private: double mVolume; @@ -112,5 +118,8 @@ class nsAudioStream // backend, the remaining samples are stored in this variable. They // will be written on the next Write() request. nsTArray mBufferOverflow; + + // PR_TRUE if this audio stream is paused. + PRPackedBool mPaused; }; #endif diff --git a/content/media/ogg/Makefile.in b/content/media/ogg/Makefile.in index 6ce9b92c4793..d8eff6105e47 100644 --- a/content/media/ogg/Makefile.in +++ b/content/media/ogg/Makefile.in @@ -49,11 +49,15 @@ LIBXUL_LIBRARY = 1 EXPORTS += \ nsChannelReader.h \ nsOggDecoder.h \ + nsOggCodecState.h \ $(NULL) CPPSRCS = \ nsChannelReader.cpp \ nsOggDecoder.cpp \ + nsOggCodecState.cpp \ + nsOggReader.cpp \ + nsOggPlayStateMachine.cpp \ $(NULL) FORCE_STATIC_LIB = 1 diff --git a/content/media/ogg/nsOggCodecState.cpp b/content/media/ogg/nsOggCodecState.cpp new file mode 100644 index 000000000000..982b60cd2fed --- /dev/null +++ b/content/media/ogg/nsOggCodecState.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ +#include "nsDebug.h" +#include "nsOggCodecState.h" +#include "nsOggDecoder.h" +#include +#include "nsTraceRefcnt.h" +#include "nsOggHacks.h" + +/* + The maximum height and width of the video. Used for + sanitizing the memory allocation of the RGB buffer. + The maximum resolution we anticipate encountering in the + wild is 2160p - 3840x2160 pixels. +*/ +#define MAX_VIDEO_WIDTH 4000 +#define MAX_VIDEO_HEIGHT 3000 + +// Adds two 64bit numbers, retuns PR_TRUE if addition succeeded, or PR_FALSE +// if addition would result in an overflow. +static PRBool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult); + +// 64 bit integer multiplication with overflow checking. Returns PR_TRUE +// if the multiplication was successful, or PR_FALSE if the operation resulted +// in an integer overflow. +static PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult); + +// Defined in nsOggReader.cpp. +extern PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult); + + +nsOggCodecState* +nsOggCodecState::Create(ogg_page* aPage) +{ + nsAutoPtr codecState; + if (aPage->body_len > 6 && memcmp(aPage->body+1, "theora", 6) == 0) { + codecState = new nsTheoraState(aPage); + } else if (aPage->body_len > 6 && memcmp(aPage->body+1, "vorbis", 6) == 0) { + codecState = new nsVorbisState(aPage); + } else if (aPage->body_len > 8 && memcmp(aPage->body, "fishead\0", 8) == 0) { + codecState = new nsSkeletonState(aPage); + } else { + codecState = new nsOggCodecState(aPage); + } + return codecState->nsOggCodecState::Init() ? codecState.forget() : nsnull; +} + +nsOggCodecState::nsOggCodecState(ogg_page* aBosPage) : + mPacketCount(0), + mSerial(ogg_page_serialno(aBosPage)), + mActive(PR_FALSE), + mDoneReadingHeaders(PR_FALSE) +{ + MOZ_COUNT_CTOR(nsOggCodecState); + memset(&mState, 0, sizeof(ogg_stream_state)); +} + +nsOggCodecState::~nsOggCodecState() { + MOZ_COUNT_DTOR(nsOggCodecState); + int ret = ogg_stream_clear(&mState); + NS_ASSERTION(ret == 0, "ogg_stream_clear failed"); +} + +nsresult nsOggCodecState::Reset() { + if (ogg_stream_reset(&mState) != 0) { + return NS_ERROR_FAILURE; + } + mBuffer.Erase(); + return NS_OK; +} + +PRBool nsOggCodecState::Init() { + int ret = ogg_stream_init(&mState, mSerial); + return ret == 0; +} + +void nsPageQueue::Append(ogg_page* aPage) { + ogg_page* p = new ogg_page(); + p->header_len = aPage->header_len; + p->body_len = aPage->body_len; + p->header = new unsigned char[p->header_len + p->body_len]; + p->body = p->header + p->header_len; + memcpy(p->header, aPage->header, p->header_len); + memcpy(p->body, aPage->body, p->body_len); + nsDeque::Push(p); +} + +PRBool nsOggCodecState::PageInFromBuffer() { + if (mBuffer.IsEmpty()) + return PR_FALSE; + ogg_page *p = mBuffer.PeekFront(); + int ret = ogg_stream_pagein(&mState, p); + NS_ENSURE_TRUE(ret == 0, PR_FALSE); + mBuffer.PopFront(); + delete p->header; + delete p; + return PR_TRUE; +} + +nsTheoraState::nsTheoraState(ogg_page* aBosPage) : + nsOggCodecState(aBosPage), + mSetup(0), + mCtx(0), + mFrameDuration(0), + mFrameRate(0), + mAspectRatio(0) +{ + MOZ_COUNT_CTOR(nsTheoraState); + th_info_init(&mInfo); + th_comment_init(&mComment); +} + +nsTheoraState::~nsTheoraState() { + MOZ_COUNT_DTOR(nsTheoraState); + th_setup_free(mSetup); + th_decode_free(mCtx); + th_comment_clear(&mComment); + th_info_clear(&mInfo); +} + +PRBool nsTheoraState::Init() { + if (!mActive) + return PR_FALSE; + mCtx = th_decode_alloc(&mInfo, mSetup); + if (mCtx == NULL) { + return mActive = PR_FALSE; + } + + PRUint32 n = mInfo.fps_numerator; + PRUint32 d = mInfo.fps_denominator; + + mFrameRate = (n == 0 || d == 0) ? + 0.0 : static_cast(n) / static_cast(d); + + PRUint32 c; + if (!MulOverflow32(1000, d, c)) { + return mActive = PR_FALSE; + } + mFrameDuration = c / n; + + n = mInfo.aspect_numerator; + d = mInfo.aspect_denominator; + mAspectRatio = (n == 0 || d == 0) ? + 1.0 : static_cast(n) / static_cast(d); + + // Ensure the frame isn't larger than our prescribed maximum. + PRUint32 pixels; + if (!MulOverflow32(mInfo.pic_width, mInfo.pic_height, pixels) || + pixels > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT || + pixels == 0) + { + return mActive = PR_FALSE; + } + + return PR_TRUE; +} + +PRBool +nsTheoraState::DecodeHeader(ogg_packet* aPacket) +{ + mPacketCount++; + int ret = th_decode_headerin(&mInfo, + &mComment, + &mSetup, + aPacket); + + // We must determine when we've read the last header packet. + // th_decode_headerin() does not tell us when it's read the last header, so + // we must keep track of the headers externally. + // + // There are 3 header packets, the Identification, Comment, and Setup + // headers, which must be in that order. If they're out of order, the file + // is invalid. If we've successfully read a header, and it's the setup + // header, then we're done reading headers. The first byte of each packet + // determines it's type as follows: + // 0x80 -> Identification header + // 0x81 -> Comment header + // 0x82 -> Setup header + // See http://www.theora.org/doc/Theora.pdf Chapter 6, "Bitstream Headers", + // for more details of the Ogg/Theora containment scheme. + PRBool isSetupHeader = aPacket->bytes > 0 && aPacket->packet[0] == 0x82; + if (ret < 0 || mPacketCount > 3) { + // We've received an error, or the first three packets weren't valid + // header packets, assume bad input, and don't activate the bitstream. + mDoneReadingHeaders = PR_TRUE; + } else if (ret > 0 && isSetupHeader && mPacketCount == 3) { + // Successfully read the three header packets. + mDoneReadingHeaders = PR_TRUE; + mActive = PR_TRUE; + } + return mDoneReadingHeaders; +} + +PRInt64 +nsTheoraState::Time(PRInt64 granulepos) { + if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) { + return -1; + } + PRInt64 t = 0; + PRInt64 frameno = th_granule_frame(mCtx, granulepos); + if (!AddOverflow(frameno, 1, t)) + return -1; + if (!MulOverflow(t, 1000, t)) + return -1; + if (!MulOverflow(t, mInfo.fps_denominator, t)) + return -1; + return t / mInfo.fps_numerator; +} + +PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) { + if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) { + return -1; + } + PRInt64 t = 0; + PRInt64 frameno = th_granule_frame(mCtx, granulepos); + if (!MulOverflow(frameno, 1000, t)) + return -1; + if (!MulOverflow(t, mInfo.fps_denominator, t)) + return -1; + return t / mInfo.fps_numerator; +} + +PRInt64 +nsTheoraState::MaxKeyframeOffset() +{ + // Determine the maximum time in milliseconds by which a key frame could + // offset for the theora bitstream. Theora granulepos encode time as: + // ((key_frame_number << granule_shift) + frame_offset). + // Therefore the maximum possible time by which any frame could be offset + // from a keyframe is the duration of (1 << granule_shift) - 1) frames. + PRInt64 frameDuration; + PRInt64 keyframeDiff; + + PRInt64 shift = mInfo.keyframe_granule_shift; + + // Max number of frames keyframe could possibly be offset. + keyframeDiff = (1 << shift) - 1; + + // Length of frame in ms. + PRInt64 d = 0; // d will be 0 if multiplication overflows. + MulOverflow(1000, mInfo.fps_denominator, d); + frameDuration = d / mInfo.fps_numerator; + + // Total time in ms keyframe can be offset from any given frame. + return frameDuration * keyframeDiff; +} + +nsresult nsVorbisState::Reset() +{ + nsresult res = NS_OK; + if (mActive && vorbis_synthesis_restart(&mDsp) != 0) { + res = NS_ERROR_FAILURE; + } + if (NS_FAILED(nsOggCodecState::Reset())) { + return NS_ERROR_FAILURE; + } + return res; +} + +nsVorbisState::nsVorbisState(ogg_page* aBosPage) : + nsOggCodecState(aBosPage) +{ + MOZ_COUNT_CTOR(nsVorbisState); + vorbis_info_init(&mInfo); + vorbis_comment_init(&mComment); + memset(&mDsp, 0, sizeof(vorbis_dsp_state)); + memset(&mBlock, 0, sizeof(vorbis_block)); +} + +nsVorbisState::~nsVorbisState() { + MOZ_COUNT_DTOR(nsVorbisState); + vorbis_block_clear(&mBlock); + vorbis_dsp_clear(&mDsp); + vorbis_info_clear(&mInfo); + vorbis_comment_clear(&mComment); +} + +PRBool nsVorbisState::DecodeHeader(ogg_packet* aPacket) { + mPacketCount++; + int ret = vorbis_synthesis_headerin(&mInfo, + &mComment, + aPacket); + // We must determine when we've read the last header packet. + // vorbis_synthesis_headerin() does not tell us when it's read the last + // header, so we must keep track of the headers externally. + // + // There are 3 header packets, the Identification, Comment, and Setup + // headers, which must be in that order. If they're out of order, the file + // is invalid. If we've successfully read a header, and it's the setup + // header, then we're done reading headers. The first byte of each packet + // determines it's type as follows: + // 0x1 -> Identification header + // 0x3 -> Comment header + // 0x5 -> Setup header + // For more details of the Vorbis/Ogg containment scheme, see the Vorbis I + // Specification, Chapter 4, Codec Setup and Packet Decode: + // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-580004 + + PRBool isSetupHeader = aPacket->bytes > 0 && aPacket->packet[0] == 0x5; + + if (ret < 0 || mPacketCount > 3) { + // We've received an error, or the first three packets weren't valid + // header packets, assume bad input, and don't activate the bitstream. + mDoneReadingHeaders = PR_TRUE; + } else if (ret == 0 && isSetupHeader && mPacketCount == 3) { + // Successfully read the three header packets, activate the bitstream. + mDoneReadingHeaders = PR_TRUE; + mActive = PR_TRUE; + } + return mDoneReadingHeaders; +} + +PRBool nsVorbisState::Init() +{ + if (!mActive) + return PR_FALSE; + + int ret = vorbis_synthesis_init(&mDsp, &mInfo); + if (ret != 0) { + NS_WARNING("vorbis_synthesis_init() failed initializing vorbis bitstream"); + return mActive = PR_FALSE; + } + ret = vorbis_block_init(&mDsp, &mBlock); + if (ret != 0) { + NS_WARNING("vorbis_block_init() failed initializing vorbis bitstream"); + if (mActive) { + vorbis_dsp_clear(&mDsp); + } + return mActive = PR_FALSE; + } + return PR_TRUE; +} + +PRInt64 nsVorbisState::Time(PRInt64 granulepos) { + if (granulepos == -1 || !mActive || mDsp.vi->rate == 0) { + return -1; + } + PRInt64 t = 0; + MulOverflow(1000, granulepos, t); + return t / mDsp.vi->rate; +} + +nsSkeletonState::nsSkeletonState(ogg_page* aBosPage) + : nsOggCodecState(aBosPage) +{ + MOZ_COUNT_CTOR(nsSkeletonState); +} + +nsSkeletonState::~nsSkeletonState() +{ + MOZ_COUNT_DTOR(nsSkeletonState); +} + +PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket) +{ + if (aPacket->e_o_s) { + mActive = PR_TRUE; + mDoneReadingHeaders = PR_TRUE; + } + return mDoneReadingHeaders; +} + +// Adds two 64bit numbers, retuns PR_TRUE if addition succeeded, or PR_FALSE +// if addition would result in an overflow. +static PRBool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) { + if (b < 1) { + if (PR_INT64_MIN - b <= a) { + aResult = a + b; + return PR_TRUE; + } + } else if (PR_INT64_MAX - b >= a) { + aResult = a + b; + return PR_TRUE; + } + return PR_FALSE; +} + +// 64 bit integer multiplication with overflow checking. Returns PR_TRUE +// if the multiplication was successful, or PR_FALSE if the operation resulted +// in an integer overflow. +static PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) { + // We break a multiplication a * b into of sign_a * sign_b * abs(a) * abs(b) + // + // This is equivalent to: + // + // (sign_a * sign_b) * ((a_hi * 2^32) + a_lo) * ((b_hi * 2^32) + b_lo) + // + // Which is equivalent to: + // + // (sign_a * sign_b) * + // ((a_hi * b_hi << 64) + + // (a_hi * b_lo << 32) + (a_lo * b_hi << 32) + + // a_lo * b_lo) + // + // So to check if a*b overflows, we must check each sub part of the above + // sum. + // + // Note: -1 * PR_INT64_MIN == PR_INT64_MIN ; we can't negate PR_INT64_MIN! + // Note: Shift of negative numbers is undefined. + // + // Figure out the sign after multiplication. Then we can just work with + // unsigned numbers. + PRInt64 sign = (!(a < 0) == !(b < 0)) ? 1 : -1; + + PRInt64 abs_a = (a < 0) ? -a : a; + PRInt64 abs_b = (b < 0) ? -b : b; + + if (abs_a < 0) { + NS_ASSERTION(a == PR_INT64_MIN, "How else can this happen?"); + if (b == 0 || b == 1) { + aResult = a * b; + return PR_TRUE; + } else { + return PR_FALSE; + } + } + + if (abs_b < 0) { + NS_ASSERTION(b == PR_INT64_MIN, "How else can this happen?"); + if (a == 0 || a == 1) { + aResult = a * b; + return PR_TRUE; + } else { + return PR_FALSE; + } + } + + NS_ASSERTION(abs_a >= 0 && abs_b >= 0, "abs values must be non-negative"); + + PRInt64 a_hi = abs_a >> 32; + PRInt64 a_lo = abs_a & 0xFFFFFFFF; + PRInt64 b_hi = abs_b >> 32; + PRInt64 b_lo = abs_b & 0xFFFFFFFF; + + NS_ASSERTION((a_hi<<32) + a_lo == abs_a, "Partition must be correct"); + NS_ASSERTION((b_hi<<32) + b_lo == abs_b, "Partition must be correct"); + + // In the sub-equation (a_hi * b_hi << 64), if a_hi or b_hi + // are non-zero, this will overflow as it's shifted by 64. + // Abort if this overflows. + if (a_hi != 0 && b_hi != 0) { + return PR_FALSE; + } + + // We can now assume that either a_hi or b_hi is 0. + NS_ASSERTION(a_hi == 0 || b_hi == 0, "One of these must be 0"); + + // Next we calculate: + // (a_hi * b_lo << 32) + (a_lo * b_hi << 32) + // We can factor this as: + // (a_hi * b_lo + a_lo * b_hi) << 32 + PRInt64 q = a_hi * b_lo + a_lo * b_hi; + if (q > PR_INT32_MAX) { + // q will overflow when we shift by 32; abort. + return PR_FALSE; + } + q <<= 32; + + // Both a_lo and b_lo are less than INT32_MAX, so can't overflow. + PRUint64 lo = a_lo * b_lo; + if (lo > PR_INT64_MAX) { + return PR_FALSE; + } + + // Add the final result. We must check for overflow during addition. + if (!AddOverflow(q, static_cast(lo), aResult)) { + return PR_FALSE; + } + + aResult *= sign; + NS_ASSERTION(a * b == aResult, "We didn't overflow, but result is wrong!"); + return PR_TRUE; +} diff --git a/content/media/ogg/nsOggCodecState.h b/content/media/ogg/nsOggCodecState.h new file mode 100644 index 000000000000..2b87584e7746 --- /dev/null +++ b/content/media/ogg/nsOggCodecState.h @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ +#if !defined(nsOggCodecState_h_) +#define nsOggCodecState_h_ + +#include +#include +#include +#include + +class OggPageDeallocator : public nsDequeFunctor { + virtual void* operator() (void* aPage) { + ogg_page* p = static_cast(aPage); + delete p->header; + delete p; + return nsnull; + } +}; + +// A queue of ogg_pages. When we read a page, and it's not from the bitstream +// which we're looking for a page for, we buffer the page in the nsOggCodecState, +// rather than pushing it immediately into the ogg_stream_state object. This +// is because if we're skipping up to the next keyframe in very large frame +// sized videos, there may be several megabytes of data between keyframes, +// and the ogg_stream_state would end up resizing its buffer every time we +// added a new 4K page to the bitstream, which kills performance on Windows. +class nsPageQueue : private nsDeque { +public: + nsPageQueue() : nsDeque(new OggPageDeallocator()) {} + ~nsPageQueue() { Erase(); } + PRBool IsEmpty() { return nsDeque::GetSize() == 0; } + void Append(ogg_page* aPage); + ogg_page* PopFront() { return static_cast(nsDeque::PopFront()); } + ogg_page* PeekFront() { return static_cast(nsDeque::PeekFront()); } + void Erase() { nsDeque::Erase(); } +}; + +// Encapsulates the data required for decoding an ogg bitstream and for +// converting granulepos to timestamps. +class nsOggCodecState { + public: + // Ogg types we know about + enum CodecType { + TYPE_VORBIS=0, + TYPE_THEORA=1, + TYPE_SKELETON=2, + TYPE_UNKNOWN=3 + }; + + public: + nsOggCodecState(ogg_page* aBosPage); + virtual ~nsOggCodecState(); + + // Factory for creating nsCodecStates. + static nsOggCodecState* Create(ogg_page* aPage); + + virtual CodecType GetType() { return TYPE_UNKNOWN; } + + // Reads a header packet. Returns PR_TRUE when last header has been read. + virtual PRBool DecodeHeader(ogg_packet* aPacket) { + return (mDoneReadingHeaders = PR_TRUE); + } + + // Returns the end time that a granulepos represents. + virtual PRInt64 Time(PRInt64 granulepos) { return -1; } + + // Returns the start time that a granulepos represents. + virtual PRInt64 StartTime(PRInt64 granulepos) { return -1; } + + // Initializes the codec state. + virtual PRBool Init(); + + // Returns PR_TRUE when this bitstream has finished reading all its + // header packets. + PRBool DoneReadingHeaders() { return mDoneReadingHeaders; } + + // Deactivates the bitstream. Only the primary video and audio bitstreams + // should be active. + void Deactivate() { mActive = PR_FALSE; } + + // Resets decoding state. + virtual nsresult Reset(); + + // Clones a page and adds it to our buffer of pages which we'll insert to + // the bitstream at a later time (using PageInFromBuffer()). Memory stored in + // cloned pages is freed when Reset() or PageInFromBuffer() are called. + inline void AddToBuffer(ogg_page* aPage) { mBuffer.Append(aPage); } + + // Returns PR_TRUE if we had a buffered page and we successfully inserted it + // into the bitstream. + PRBool PageInFromBuffer(); + +public: + + // Number of packets read. + PRUint64 mPacketCount; + + // Serial number of the bitstream. + PRUint32 mSerial; + + // Ogg specific state. + ogg_stream_state mState; + + // Buffer of pages which we've not yet inserted into the ogg_stream_state. + nsPageQueue mBuffer; + + // Is the bitstream active; whether we're decoding and playing this bitstream. + PRPackedBool mActive; + + // PR_TRUE when all headers packets have been read. + PRPackedBool mDoneReadingHeaders; +}; + +class nsVorbisState : public nsOggCodecState { +public: + nsVorbisState(ogg_page* aBosPage); + virtual ~nsVorbisState(); + + virtual CodecType GetType() { return TYPE_VORBIS; } + virtual PRBool DecodeHeader(ogg_packet* aPacket); + virtual PRInt64 Time(PRInt64 granulepos); + virtual PRBool Init(); + virtual nsresult Reset(); + + vorbis_info mInfo; + vorbis_comment mComment; + vorbis_dsp_state mDsp; + vorbis_block mBlock; +}; + +class nsTheoraState : public nsOggCodecState { +public: + nsTheoraState(ogg_page* aBosPage); + virtual ~nsTheoraState(); + + virtual CodecType GetType() { return TYPE_THEORA; } + virtual PRBool DecodeHeader(ogg_packet* aPacket); + virtual PRInt64 Time(PRInt64 granulepos); + virtual PRInt64 StartTime(PRInt64 granulepos); + virtual PRBool Init(); + + // Returns the maximum number of milliseconds which a keyframe can be offset + // from any given interframe. + PRInt64 MaxKeyframeOffset(); + + th_info mInfo; + th_comment mComment; + th_setup_info *mSetup; + th_dec_ctx* mCtx; + + // Frame duration in ms. + PRUint32 mFrameDuration; + + // Number of frames per second. + float mFrameRate; + + float mAspectRatio; +}; + +class nsSkeletonState : public nsOggCodecState { +public: + nsSkeletonState(ogg_page* aBosPage); + virtual ~nsSkeletonState(); + virtual CodecType GetType() { return TYPE_SKELETON; } + virtual PRBool DecodeHeader(ogg_packet* aPacket); + virtual PRInt64 Time(PRInt64 granulepos) { return -1; } + virtual PRBool Init() { return PR_TRUE; } +}; + +#endif diff --git a/content/media/ogg/nsOggDecoder.cpp b/content/media/ogg/nsOggDecoder.cpp index 37bcaf58e7aa..b4ba4dcc7b62 100644 --- a/content/media/ogg/nsOggDecoder.cpp +++ b/content/media/ogg/nsOggDecoder.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Chris Double + * Chris Pearce * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,1945 +37,31 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsOggDecoder.h" - +#include "nsOggPlayStateMachine.h" #include -#include "prmem.h" -#include "nsIFrame.h" -#include "nsIDocument.h" -#include "nsThreadUtils.h" -#include "nsIDOMHTMLMediaElement.h" #include "nsNetUtil.h" #include "nsAudioStream.h" -#include "nsChannelReader.h" #include "nsHTMLVideoElement.h" #include "nsIObserver.h" #include "nsIObserverService.h" -#include "nsAutoLock.h" #include "nsTArray.h" -#include "nsNetUtil.h" - -using mozilla::TimeDuration; -using mozilla::TimeStamp; -using namespace mozilla::layers; +#include "nsOggCodecState.h" +#include "nsOggDecoder.h" +#include "nsOggReader.h" #ifdef PR_LOGGING -static PRLogModuleInfo* gOggDecoderLog; +PRLogModuleInfo* gOggDecoderLog; #define LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) #else #define LOG(type, msg) #endif -/* - The maximum height and width of the video. Used for - sanitizing the memory allocation of the RGB buffer. - The maximum resolution we anticipate encountering in the - wild is 2160p - 3840x2160 pixels. -*/ -#define MAX_VIDEO_WIDTH 4000 -#define MAX_VIDEO_HEIGHT 3000 - -// The number of entries in oggplay buffer list. This value is totally -// arbitrary. Note that the actual number of video/audio frames buffered is -// twice this, because the current implementation releases OggPlay's buffer -// entries and stores references or copies of the underlying data in the -// FrameQueue. -#define OGGPLAY_BUFFER_SIZE 5 - -// The number of frames to read before audio callback is called. -// This value is the one used by the oggplay examples. -#define OGGPLAY_FRAMES_PER_CALLBACK 2048 - -// Offset into Ogg buffer containing audio information. This value -// is the one used by the oggplay examples. -#define OGGPLAY_AUDIO_OFFSET 250L - -// Wait this number of seconds when buffering, then leave and play -// as best as we can if the required amount of data hasn't been -// retrieved. -#define BUFFERING_WAIT 15 - -// The amount of data to retrieve during buffering is computed based -// on the download rate. BUFFERING_MIN_RATE is the minimum download -// rate to be used in that calculation to help avoid constant buffering -// attempts at a time when the average download rate has not stabilised. -#define BUFFERING_MIN_RATE 50000 -#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x)) - -// The number of seconds of buffer data before buffering happens -// based on current playback rate. -#define BUFFERING_SECONDS_LOW_WATER_MARK 1 - -// The minimum size buffered byte range inside which we'll consider -// trying a bounded-seek. When we seek, we first try to seek inside all -// buffered ranges larger than this, and if they all fail we fall back to -// an unbounded seek over the whole media. 64K is approximately 16 pages. -#define MIN_BOUNDED_SEEK_SIZE (64 * 1024) - -class nsOggStepDecodeEvent; - -/* - All reading (including seeks) from the nsMediaStream are done on the - decoding thread. The decoder thread is informed before closing that - the stream is about to close via the Shutdown - event. oggplay_prepare_for_close is called before sending the - shutdown event to tell liboggplay to shutdown. - - This call results in oggplay internally not calling any - read/write/seek/tell methods, and returns a value that results in - stopping the decoder thread. - - oggplay_close is called in the destructor which results in the media - stream being closed. This is how the nsMediaStream contract that no - read/seeking must occur during or after Close is called is enforced. - - This object keeps pointers to the nsOggDecoder and nsChannelReader - objects. Since the lifetime of nsOggDecodeStateMachine is - controlled by nsOggDecoder it will never have a stale reference to - these objects. The reader is destroyed by the call to oggplay_close - which is done in the destructor so again this will never be a stale - reference. - - All internal state is synchronised via the decoder monitor. NotifyAll - on the monitor is called when the state of the state machine is changed - by the main thread. The following changes to state cause a notify: - - mState and data related to that state changed (mSeekTime, etc) - Ogg Metadata Loaded - First Frame Loaded - Frame decoded - - See nsOggDecoder.h for more details. -*/ -class nsOggDecodeStateMachine : public nsRunnable -{ - friend class nsOggStepDecodeEvent; -public: - // Object to hold the decoded data from a frame - class FrameData { - public: - FrameData() : - mVideoHeader(nsnull), - mVideoWidth(0), - mVideoHeight(0), - mUVWidth(0), - mUVHeight(0), - mDecodedFrameTime(0.0), - mTime(0.0) - { - MOZ_COUNT_CTOR(FrameData); - } - - ~FrameData() - { - MOZ_COUNT_DTOR(FrameData); - ClearVideoHeader(); - } - - void ClearVideoHeader() { - if (mVideoHeader) { - oggplay_callback_info_unlock_item(mVideoHeader); - mVideoHeader = nsnull; - } - } - - // Write the audio data from the frame to the Audio stream. - void Write(nsAudioStream* aStream) - { - aStream->Write(mAudioData.Elements(), mAudioData.Length()); - mAudioData.Clear(); - } - - void SetVideoHeader(OggPlayDataHeader* aVideoHeader) - { - NS_ABORT_IF_FALSE(!mVideoHeader, "Frame already owns a video header"); - mVideoHeader = aVideoHeader; - oggplay_callback_info_lock_item(mVideoHeader); - } - - // The position in the stream where this frame ended, in bytes - PRInt64 mEndStreamPosition; - OggPlayDataHeader* mVideoHeader; - nsTArray mAudioData; - int mVideoWidth; - int mVideoHeight; - int mUVWidth; - int mUVHeight; - float mDecodedFrameTime; - float mTime; - OggPlayStreamInfo mState; - }; - - // A queue of decoded video frames. - class FrameQueue - { - public: - FrameQueue() : - mHead(0), - mTail(0), - mCount(0) - { - } - - void Push(FrameData* frame) - { - NS_ASSERTION(!IsFull(), "FrameQueue is full"); - mQueue[mTail] = frame; - mTail = (mTail+1) % OGGPLAY_BUFFER_SIZE; - ++mCount; - } - - FrameData* Peek() const - { - NS_ASSERTION(mCount > 0, "FrameQueue is empty"); - - return mQueue[mHead]; - } - - FrameData* Pop() - { - NS_ASSERTION(mCount, "FrameQueue is empty"); - - FrameData* result = mQueue[mHead]; - mHead = (mHead + 1) % OGGPLAY_BUFFER_SIZE; - --mCount; - return result; - } - - PRBool IsEmpty() const - { - return mCount == 0; - } - - PRUint32 GetCount() const - { - return mCount; - } - - PRBool IsFull() const - { - return mCount == OGGPLAY_BUFFER_SIZE; - } - - PRUint32 ResetTimes(float aPeriod) - { - PRUint32 frames = 0; - if (mCount > 0) { - PRUint32 current = mHead; - do { - mQueue[current]->mTime = frames * aPeriod; - frames += 1; - current = (current + 1) % OGGPLAY_BUFFER_SIZE; - } while (current != mTail); - } - return frames; - } - - private: - FrameData* mQueue[OGGPLAY_BUFFER_SIZE]; - PRUint32 mHead; - PRUint32 mTail; - // This isn't redundant with mHead/mTail, since when mHead == mTail - // it's ambiguous whether the queue is full or empty - PRUint32 mCount; - }; - - // Enumeration for the valid states - enum State { - DECODER_STATE_DECODING_METADATA, - DECODER_STATE_DECODING, - DECODER_STATE_SEEKING, - DECODER_STATE_BUFFERING, - DECODER_STATE_COMPLETED, - DECODER_STATE_SHUTDOWN - }; - - nsOggDecodeStateMachine(nsOggDecoder* aDecoder); - ~nsOggDecodeStateMachine(); - - // Cause state transitions. These methods obtain the decoder monitor - // to synchronise the change of state, and to notify other threads - // that the state has changed. - void Shutdown(); - void Decode(); - void Seek(float aTime); - void StopStepDecodeThread(nsAutoMonitor* aMonitor); - - NS_IMETHOD Run(); - - PRBool HasAudio() - { - NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA, "HasAudio() called during invalid state"); - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mAudioTrack != -1; - } - - // Decode one frame of data, returning the OggPlay error code. Must - // be called only when the current state > DECODING_METADATA. The decode - // monitor MUST NOT be locked during this call since it can take a long - // time. liboggplay internally handles locking. - // Any return value apart from those below is mean decoding cannot continue. - // E_OGGPLAY_CONTINUE = One frame decoded and put in buffer list - // E_OGGPLAY_USER_INTERRUPT = One frame decoded, buffer list is now full - // E_OGGPLAY_TIMEOUT = No frames decoded, timed out - OggPlayErrorCode DecodeFrame(); - - // Handle any errors returned by liboggplay when decoding a frame. - // Since this function can change the decoding state it must be called - // with the decoder lock held. - void HandleDecodeErrors(OggPlayErrorCode r); - - // Returns the next decoded frame of data. The caller is responsible - // for freeing the memory returned. This function must be called - // only when the current state > DECODING_METADATA. The decode - // monitor lock does not need to be locked during this call since - // liboggplay internally handles locking. - FrameData* NextFrame(); - - // Play a frame of decoded video. The decode monitor is obtained - // internally by this method for synchronisation. - void PlayFrame(); - - // Play the video data from the given frame. The decode monitor - // must be locked when calling this method. - void PlayVideo(FrameData* aFrame); - - // Plays the audio for the frame, plus any outstanding audio data - // buffered by nsAudioStream and not yet written to the - // hardware. The audio data for the frame is cleared out so - // subsequent calls with the same frame do not re-write the data. - // The decode monitor must be locked when calling this method. - void PlayAudio(FrameData* aFrame); - - // Called from the main thread to get the current frame time. The decoder - // monitor must be obtained before calling this. - float GetCurrentTime(); - - // Called from the main thread to get the duration. The decoder monitor - // must be obtained before calling this. It is in units of milliseconds. - PRInt64 GetDuration(); - - // Called from the main thread to set the duration of the media resource - // if it is able to be obtained via HTTP headers. The decoder monitor - // must be obtained before calling this. - void SetDuration(PRInt64 aDuration); - - // Called from the main thread to set whether the media resource can - // be seeked. The decoder monitor must be obtained before calling this. - void SetSeekable(PRBool aSeekable); - - // Set the audio volume. The decoder monitor must be obtained before - // calling this. - void SetVolume(float aVolume); - - // Clear the flag indicating that a playback position change event - // is currently queued. This is called from the main thread and must - // be called with the decode monitor held. - void ClearPositionChangeFlag(); - - // Called by decoder and main thread. - nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus(); - - // Must be called with the decode monitor held. Can be called by main - // thread. - PRBool HaveNextFrameData() const { - return !mDecodedFrames.IsEmpty() && - (mDecodedFrames.Peek()->mDecodedFrameTime > mCurrentFrameTime || - mDecodedFrames.GetCount() > 1); - } - - // Must be called with the decode monitor held. Can be called by main - // thread. - PRBool IsBuffering() const { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mState == nsOggDecodeStateMachine::DECODER_STATE_BUFFERING; - } - - // Must be called with the decode monitor held. Can be called by main - // thread. - PRBool IsSeeking() const { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mState == nsOggDecodeStateMachine::DECODER_STATE_SEEKING; - } - -protected: - - // Decodes from the current position until encountering a frame with time - // greater or equal to aSeekTime. - PRBool DecodeToFrame(nsAutoMonitor& aMonitor, - float aSeekTime); - - // Convert the OggPlay frame information into a format used by Gecko - // (RGB for video, float for sound, etc).The decoder monitor must be - // acquired in the scope of calls to these functions. They must be - // called only when the current state > DECODING_METADATA. - void HandleVideoData(FrameData* aFrame, int aTrackNum, OggPlayDataHeader* aVideoHeader); - void HandleAudioData(FrameData* aFrame, OggPlayAudioData* aAudioData, int aSize); - - void UpdateReadyState() { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - - nsCOMPtr event; - switch (GetNextFrameStatus()) { - case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING: - event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailableBuffering); - break; - case nsHTMLMediaElement::NEXT_FRAME_AVAILABLE: - event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameAvailable); - break; - case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE: - event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailable); - break; - default: - PR_NOT_REACHED("unhandled frame state"); - } - - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); - } - - // These methods can only be called on the decoding thread. - void LoadOggHeaders(nsChannelReader* aReader); - - // Initializes and opens the audio stream. Called from the decode - // thread only. Must be called with the decode monitor held. - void OpenAudioStream(); - - // Closes and releases resources used by the audio stream. Called - // from the decode thread only. Must be called with the decode - // monitor held. - void CloseAudioStream(); - - // Start playback of audio, either by opening or resuming the audio - // stream. Must be called with the decode monitor held. - void StartAudio(); - - // Stop playback of audio, either by closing or pausing the audio - // stream. Must be called with the decode monitor held. - void StopAudio(); - - // Start playback of media. Must be called with the decode monitor held. - // This opens or re-opens the audio stream for playback to start. - void StartPlayback(); - - // Stop playback of media. Must be called with the decode monitor held. - // This actually closes the audio stream and releases any OS resources. - void StopPlayback(); - - // Pause playback of media. Must be called with the decode monitor held. - // This does not close the OS based audio stream - it suspends it to be - // resumed later. - void PausePlayback(); - - // Resume playback of media. Must be called with the decode monitor held. - // This resumes a paused audio stream. - void ResumePlayback(); - - // Update the playback position. This can result in a timeupdate event - // and an invalidate of the frame being dispatched asynchronously if - // there is no such event currently queued. - // Only called on the decoder thread. Must be called with - // the decode monitor held. - void UpdatePlaybackPosition(float aTime); - - // Takes decoded frames from liboggplay's internal buffer and - // places them in our frame queue. Must be called with the decode - // monitor held. - void QueueDecodedFrames(); - - // Seeks the OggPlay to aTime, inside buffered byte ranges in aReader's - // media stream. - nsresult Seek(float aTime, nsChannelReader* aReader); - - // Sets the current video and audio track to active in liboggplay. - // Called from the decoder thread only. - void SetTracksActive(); - -private: - // ***** - // The follow fields are only accessed by the decoder thread - // ***** - - // The decoder object that created this state machine. The decoder - // always outlives us since it controls our lifetime. - nsOggDecoder* mDecoder; - - // The OggPlay handle. Synchronisation of calls to oggplay functions - // are handled by liboggplay. We control the lifetime of this - // object, destroying it in our destructor. - OggPlay* mPlayer; - - // Frame data containing decoded video/audio for the frame the - // current frame and the previous frame. Always accessed with monitor - // held. Written only via the decoder thread, but can be tested on - // main thread via HaveNextFrameData. - FrameQueue mDecodedFrames; - - // The time that playback started from the system clock. This is used - // for synchronising frames. It is reset after a seek as the mTime member - // of FrameData is reset to start at 0 from the first frame after a seek. - // Accessed only via the decoder thread. - TimeStamp mPlayStartTime; - - // The time that playback was most recently paused, either via - // buffering or pause. This is used to compute mPauseDuration for - // a/v sync adjustments. Accessed only via the decoder thread. - TimeStamp mPauseStartTime; - - // The total time that has been spent in completed pauses (via - // 'pause' or buffering). This is used to adjust for these - // pauses when computing a/v synchronisation. Accessed only via the - // decoder thread. - TimeDuration mPauseDuration; - - // PR_TRUE if the media is playing and the decoder has started - // the sound and adjusted the sync time for pauses. PR_FALSE - // if the media is paused and the decoder has stopped the sound - // and adjusted the sync time for pauses. Accessed only via the - // decoder thread. - PRPackedBool mPlaying; - - // Number of seconds of data video/audio data held in a frame. - // Accessed only via the decoder thread. - double mCallbackPeriod; - - // Video data. These are initially set when the metadata is loaded. - // They are only accessed from the decoder thread. - PRInt32 mVideoTrack; - float mFramerate; - float mAspectRatio; - - // Audio data. These are initially set when the metadata is loaded. - // They are only accessed from the decoder thread. - PRInt32 mAudioRate; - PRInt32 mAudioChannels; - PRInt32 mAudioTrack; - - // Time that buffering started. Used for buffering timeout and only - // accessed in the decoder thread. - TimeStamp mBufferingStart; - - // Download position where we should stop buffering. Only - // accessed in the decoder thread. - PRInt64 mBufferingEndOffset; - - // The last decoded video frame. Used for computing the sleep period - // between frames for a/v sync. Read/Write from the decode thread only. - PRUint64 mLastFrame; - - // The decoder position of the end of the last decoded video frame. - // Read/Write from the decode thread only. - PRInt64 mLastFramePosition; - - // Thread that steps through decoding each frame using liboggplay. Only accessed - // via the decode thread. - nsCOMPtr mStepDecodeThread; - - // ***** - // The follow fields are accessed by the decoder thread or - // the main thread. - // ***** - - // The decoder monitor must be obtained before modifying this state. - // NotifyAll on the monitor must be called when the state is changed by - // the main thread so the decoder thread can wake up. - State mState; - - // Position to seek to when the seek state transition occurs. The - // decoder monitor lock must be obtained before reading or writing - // this value. - float mSeekTime; - - // The audio stream resource. Used on the decode thread and the - // main thread (Via the SetVolume call). Synchronisation via - // mDecoder monitor. - nsAutoPtr mAudioStream; - - // The time of the current frame in seconds. This is referenced from - // 0.0 which is the initial start of the stream. Set by the decode - // thread, and read-only from the main thread to get the current - // time value. Synchronised via decoder monitor. - float mCurrentFrameTime; - - // The presentation times of the first frame that was decoded. This is - // the start time of the frame. This is subtracted from each frames' - // timestamp, so that playback appears to start at time 0 and end at - // time mDuration. Read/Written from the decode thread, read from the - // main thread. Synchronised via decoder monitor. - float mPlaybackStartTime; - - // Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written - // from the decode and main threads. Synchronised via decoder - // monitor. - float mVolume; - - // Duration of the media resource. It is accessed from the decoder and main - // threads. Synchronised via decoder monitor. It is in units of - // milliseconds. - PRInt64 mDuration; - - // PR_TRUE if the media resource can be seeked. Accessed from the decoder - // and main threads. Synchronised via decoder monitor. - PRPackedBool mSeekable; - - // PR_TRUE if an event to notify about a change in the playback - // position has been queued, but not yet run. It is set to PR_FALSE when - // the event is run. This allows coalescing of these events as they can be - // produced many times per second. Synchronised via decoder monitor. - PRPackedBool mPositionChangeQueued; - - // PR_TRUE if the step decode loop thread has finished decoding. It is - // written by the step decode thread and read and written by the state - // machine thread (but only written by the state machine thread while - // the step decode thread is not running). - // Synchronised via decoder monitor. - PRPackedBool mDecodingCompleted; - - // PR_TRUE if the step decode loop thread should exit now. It is - // written by the state machine thread and read by the step decode thread. - // Synchronised via decoder monitor. - PRPackedBool mExitStepDecodeThread; - - // PR_TRUE if the step decode loop has indicated that we need to buffer. - // Accessed by the step decode thread and the decode state machine thread. - // Synchronised via the decoder monitor. - PRPackedBool mBufferExhausted; - - // PR_TRUE if mDuration has a value obtained from an HTTP header. - // Read/Written from the decode and main threads. Synchronised via the - // decoder monitor. - PRPackedBool mGotDurationFromHeader; -}; - -// Event that gets posted to the thread that is responsible for decoding -// Ogg frames. Decodes each frame of an Ogg file. Locking of liboggplay -// is managed by liboggplay. The thread is created when the frames first -// need to be decoded and is shutdown when decoding is not needed (either -// completed, or seeking). -class nsOggStepDecodeEvent : public nsRunnable { -private: - // Since the lifetime of this event loop is controlled by the - // decode state machine object, it is safe to keep an - // unreferenced counted pointer to it, so we can inform - // it when we've finished decoding. - nsOggDecodeStateMachine* mDecodeStateMachine; - - // The lifetime of this player is managed by the decode state - // machine thread. This event is created and destroyed before - // the mPlayer object itself is deleted. - OggPlay* mPlayer; - -public: - nsOggStepDecodeEvent(nsOggDecodeStateMachine* machine, OggPlay* player) : - mDecodeStateMachine(machine), mPlayer(player) {} - - // Return true if we are in a state where the decoder should not be running. - PRBool InStopDecodingState() { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecodeStateMachine->mDecoder->GetMonitor()); - return - mDecodeStateMachine->mState != nsOggDecodeStateMachine::DECODER_STATE_DECODING && - mDecodeStateMachine->mState != nsOggDecodeStateMachine::DECODER_STATE_BUFFERING; - } - - // This method will block on oggplay_step_decoding when oggplay's - // internal buffers are full. It is unblocked by the decode - // state machine thread via a call to oggplay_prepare_for_close - // during the shutdown protocol. It is unblocked during seeking - // by release frames from liboggplay's frame queue. - NS_IMETHOD Run() { - OggPlayErrorCode r = E_OGGPLAY_TIMEOUT; - nsAutoMonitor mon(mDecodeStateMachine->mDecoder->GetMonitor()); - nsOggDecoder* decoder = mDecodeStateMachine->mDecoder; - NS_ASSERTION(!mDecodeStateMachine->mDecodingCompleted, - "State machine should have cleared this flag"); - - while (!mDecodeStateMachine->mExitStepDecodeThread && - !InStopDecodingState() && - (r == E_OGGPLAY_TIMEOUT || - r == E_OGGPLAY_USER_INTERRUPT || - r == E_OGGPLAY_CONTINUE)) { - if (mDecodeStateMachine->mBufferExhausted) { - mon.Wait(); - } else { - // decoder and decoder->mReader are never null here because - // they are non-null through the lifetime of the state machine - // thread, which includes the lifetime of this thread. - PRInt64 initialDownloadPosition = - decoder->mReader->Stream()->GetCachedDataEnd(decoder->mDecoderPosition); - - mon.Exit(); - r = oggplay_step_decoding(mPlayer); - mon.Enter(); - - mDecodeStateMachine->HandleDecodeErrors(r); - - // Check whether decoding the last frame required us to read data - // that wasn't available at the start of the frame. That means - // we should probably start buffering. - if (decoder->mDecoderPosition > initialDownloadPosition) { - mDecodeStateMachine->mBufferExhausted = PR_TRUE; - } - - // If PlayFrame is waiting, wake it up so we can run the - // decoder loop and move frames from the oggplay queue to our - // queue. Also needed to wake up the decoder loop that waits - // for a frame to be ready to display. - mon.NotifyAll(); - } - } - - mDecodeStateMachine->mDecodingCompleted = PR_TRUE; - return NS_OK; - } -}; - -nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder) : - mDecoder(aDecoder), - mPlayer(0), - mPlayStartTime(), - mPauseStartTime(), - mPauseDuration(0), - mPlaying(PR_FALSE), - mCallbackPeriod(1.0), - mVideoTrack(-1), - mFramerate(0.0), - mAspectRatio(1.0), - mAudioRate(0), - mAudioChannels(0), - mAudioTrack(-1), - mBufferingStart(), - mBufferingEndOffset(0), - mLastFrame(0), - mLastFramePosition(-1), - mState(DECODER_STATE_DECODING_METADATA), - mSeekTime(0.0), - mCurrentFrameTime(0.0), - mPlaybackStartTime(0.0), - mVolume(1.0), - mDuration(-1), - mSeekable(PR_TRUE), - mPositionChangeQueued(PR_FALSE), - mDecodingCompleted(PR_FALSE), - mExitStepDecodeThread(PR_FALSE), - mBufferExhausted(PR_FALSE), - mGotDurationFromHeader(PR_FALSE) -{ -} - -nsOggDecodeStateMachine::~nsOggDecodeStateMachine() -{ - while (!mDecodedFrames.IsEmpty()) { - delete mDecodedFrames.Pop(); - } - oggplay_close(mPlayer); -} - -OggPlayErrorCode nsOggDecodeStateMachine::DecodeFrame() -{ - OggPlayErrorCode r = oggplay_step_decoding(mPlayer); - return r; -} - -void nsOggDecodeStateMachine::HandleDecodeErrors(OggPlayErrorCode aErrorCode) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - - if (aErrorCode != E_OGGPLAY_TIMEOUT && - aErrorCode != E_OGGPLAY_OK && - aErrorCode != E_OGGPLAY_USER_INTERRUPT && - aErrorCode != E_OGGPLAY_CONTINUE) { - mState = DECODER_STATE_SHUTDOWN; - nsCOMPtr event = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, DecodeError); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); - } -} - -nsOggDecodeStateMachine::FrameData* nsOggDecodeStateMachine::NextFrame() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - OggPlayCallbackInfo** info = oggplay_buffer_retrieve_next(mPlayer); - if (!info) - return nsnull; - - FrameData* frame = new FrameData(); - if (!frame) { - return nsnull; - } - - frame->mTime = mCallbackPeriod * mLastFrame; - frame->mEndStreamPosition = mDecoder->mDecoderPosition; - mLastFrame += 1; - - if (mLastFramePosition >= 0) { - NS_ASSERTION(frame->mEndStreamPosition >= mLastFramePosition, - "Playback positions must not decrease without an intervening reset"); - TimeStamp base = mPlayStartTime; - if (base.IsNull()) { - // It doesn't really matter what 'base' is, so just use 'now' if - // we haven't started playback. - base = TimeStamp::Now(); - } - mDecoder->mPlaybackStatistics.Start( - base + TimeDuration::FromMilliseconds(NS_round(frame->mTime*1000))); - mDecoder->mPlaybackStatistics.AddBytes(frame->mEndStreamPosition - mLastFramePosition); - mDecoder->mPlaybackStatistics.Stop( - base + TimeDuration::FromMilliseconds(NS_round(mCallbackPeriod*mLastFrame*1000))); - mDecoder->UpdatePlaybackRate(); - } - mLastFramePosition = frame->mEndStreamPosition; - - int num_tracks = oggplay_get_num_tracks(mPlayer); - float audioTime = -1.0; - float videoTime = -1.0; - - if (mVideoTrack != -1 && - num_tracks > mVideoTrack && - oggplay_callback_info_get_type(info[mVideoTrack]) == OGGPLAY_YUV_VIDEO) { - OggPlayDataHeader** headers = oggplay_callback_info_get_headers(info[mVideoTrack]); - if (headers[0]) { - videoTime = ((float)oggplay_callback_info_get_presentation_time(headers[0]))/1000.0; - HandleVideoData(frame, mVideoTrack, headers[0]); - } - } - - // If the audio stream has finished, but there's still video frames to - // be rendered, we need to send blank audio data to the audio hardware, - // so that the audio clock, which maintains the presentation time, keeps - // incrementing. - PRBool needSilence = PR_FALSE; - - if (mAudioTrack != -1 && num_tracks > mAudioTrack) { - OggPlayDataType type = oggplay_callback_info_get_type(info[mAudioTrack]); - needSilence = (type == OGGPLAY_INACTIVE); - if (type == OGGPLAY_FLOATS_AUDIO) { - OggPlayDataHeader** headers = oggplay_callback_info_get_headers(info[mAudioTrack]); - if (headers[0]) { - audioTime = ((float)oggplay_callback_info_get_presentation_time(headers[0]))/1000.0; - int required = oggplay_callback_info_get_required(info[mAudioTrack]); - for (int j = 0; j < required; ++j) { - int size = oggplay_callback_info_get_record_size(headers[j]); - OggPlayAudioData* audio_data = oggplay_callback_info_get_audio_data(headers[j]); - HandleAudioData(frame, audio_data, size); - } - } - } - } - - if (needSilence) { - // Write silence to keep audio clock moving for av sync - size_t count = mAudioChannels * mAudioRate * mCallbackPeriod; - // count must be evenly divisble by number of channels. - count = mAudioChannels * PRInt32(NS_ceil(mAudioRate*mCallbackPeriod)); - float* data = frame->mAudioData.AppendElements(count); - if (data) { - memset(data, 0, sizeof(float)*count); - } - } - - // Pick one stream to act as the reference track to indicate if the - // stream has ended, seeked, etc. - if (videoTime >= 0) { - frame->mState = oggplay_callback_info_get_stream_info(info[mVideoTrack]); - frame->mDecodedFrameTime = videoTime; - } else if (audioTime >= 0) { - frame->mState = oggplay_callback_info_get_stream_info(info[mAudioTrack]); - frame->mDecodedFrameTime = audioTime; - } else { - NS_WARNING("Encountered frame with no audio or video data"); - frame->mState = OGGPLAY_STREAM_UNINITIALISED; - frame->mDecodedFrameTime = 0.0; - } - - oggplay_buffer_release(mPlayer, info); - return frame; -} - -void nsOggDecodeStateMachine::HandleVideoData(FrameData* aFrame, int aTrackNum, OggPlayDataHeader* aVideoHeader) { - if (!aVideoHeader) - return; - - int y_width = 0; - int y_height = 0; - oggplay_get_video_y_size(mPlayer, aTrackNum, &y_width, &y_height); - int uv_width = 0; - int uv_height = 0; - oggplay_get_video_uv_size(mPlayer, aTrackNum, &uv_width, &uv_height); - - if (y_width >= MAX_VIDEO_WIDTH || y_height >= MAX_VIDEO_HEIGHT) { - return; - } - - aFrame->mVideoWidth = y_width; - aFrame->mVideoHeight = y_height; - aFrame->mUVWidth = uv_width; - aFrame->mUVHeight = uv_height; - aFrame->SetVideoHeader(aVideoHeader); -} - -void nsOggDecodeStateMachine::HandleAudioData(FrameData* aFrame, OggPlayAudioData* aAudioData, int aSize) { - // 'aSize' is number of samples. Multiply by number of channels to - // get the actual number of floats being sent. - int size = aSize * mAudioChannels; - - aFrame->mAudioData.AppendElements(reinterpret_cast(aAudioData), size); -} - -void nsOggDecodeStateMachine::PlayFrame() { - // Play a frame of video and/or audio data. - // If we are playing we open the audio stream if needed - // If there are decoded frames in the queue a single frame - // is popped off and played if it is time for that frame - // to display. - // If it is not time yet to display the frame, we either - // continue decoding frames, or wait until it is time for - // the frame to display if the queue is full. - // - // If the decode state is not PLAYING then we just exit - // so we can continue decoding frames. If the queue is - // full we wait for a state change. - nsAutoMonitor mon(mDecoder->GetMonitor()); - - if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { - if (!mPlaying) { - ResumePlayback(); - } - - if (!mDecodedFrames.IsEmpty()) { - FrameData* frame = mDecodedFrames.Peek(); - if (frame->mState == OGGPLAY_STREAM_JUST_SEEKED) { - // After returning from a seek all mTime members of - // FrameData start again from a time position of 0. - // Reset the play start time. - mPlayStartTime = TimeStamp::Now(); - mPauseDuration = TimeDuration(0); - frame->mState = OGGPLAY_STREAM_INITIALISED; - } - - double time; - PRUint32 hasAudio = frame->mAudioData.Length(); - for (;;) { - // Even if the frame has had its audio data written we call - // PlayAudio to ensure that any data we have buffered in the - // nsAudioStream is written to the hardware. - PlayAudio(frame); - double hwtime = mAudioStream && hasAudio ? mAudioStream->GetPosition() : -1.0; - time = hwtime < 0.0 ? - (TimeStamp::Now() - mPlayStartTime - mPauseDuration).ToSeconds() : - hwtime; - // Resynchronize the system clock against the audio clock. - if (hwtime >= 0.0) { - mPlayStartTime = TimeStamp::Now(); - mPlayStartTime -= TimeDuration::FromMilliseconds(hwtime * 1000.0); - mPauseDuration = TimeDuration(0); - } - // Is it time for the next frame? Using an integer here avoids f.p. - // rounding errors that can cause multiple 0ms waits (Bug 495352) - PRInt64 wait = PRInt64((frame->mTime - time)*1000); - if (wait <= 0) - break; - mon.Wait(PR_MillisecondsToInterval(wait)); - if (mState == DECODER_STATE_SHUTDOWN) - return; - } - - mDecodedFrames.Pop(); - QueueDecodedFrames(); - - // Skip frames up to the one we should be showing. - while (!mDecodedFrames.IsEmpty() && time >= mDecodedFrames.Peek()->mTime) { - LOG(PR_LOG_DEBUG, ("%p Skipping frame time %f with audio at time %f", mDecoder, mDecodedFrames.Peek()->mTime, time)); - PlayAudio(frame); - delete frame; - frame = mDecodedFrames.Peek(); - mDecodedFrames.Pop(); - } - if (time < frame->mTime + mCallbackPeriod) { - PlayAudio(frame); - PlayVideo(frame); - mDecoder->mPlaybackPosition = frame->mEndStreamPosition; - UpdatePlaybackPosition(frame->mDecodedFrameTime); - delete frame; - } - else { - PlayAudio(frame); - delete frame; - frame = 0; - } - } - } - else { - if (mPlaying) { - PausePlayback(); - } - - if (mState == DECODER_STATE_DECODING) { - mon.Wait(); - if (mState == DECODER_STATE_SHUTDOWN) { - return; - } - } - } -} - -static void ToARGBHook(const PlanarYCbCrImage::Data& aData, PRUint8* aOutput) -{ - OggPlayYUVChannels yuv; - NS_ASSERTION(aData.mYStride == aData.mYSize.width, - "Stride not supported"); - NS_ASSERTION(aData.mCbCrStride == aData.mCbCrSize.width, - "Stride not supported"); - yuv.ptry = aData.mYChannel; - yuv.ptru = aData.mCbChannel; - yuv.ptrv = aData.mCrChannel; - yuv.uv_width = aData.mCbCrSize.width; - yuv.uv_height = aData.mCbCrSize.height; - yuv.y_width = aData.mYSize.width; - yuv.y_height = aData.mYSize.height; - - OggPlayRGBChannels rgb; - rgb.ptro = aOutput; - rgb.rgb_width = aData.mYSize.width; - rgb.rgb_height = aData.mYSize.height; - - oggplay_yuv2bgra(&yuv, &rgb); -} - -void nsOggDecodeStateMachine::PlayVideo(FrameData* aFrame) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (aFrame && aFrame->mVideoHeader) { - ImageContainer* container = mDecoder->GetImageContainer(); - // Currently our Ogg decoder only knows how to output to PLANAR_YCBCR - // format. - Image::Format format = Image::PLANAR_YCBCR; - nsRefPtr image; - if (container) { - image = container->CreateImage(&format, 1); - } - if (image) { - NS_ASSERTION(image->GetFormat() == Image::PLANAR_YCBCR, - "Wrong format?"); - PlanarYCbCrImage* videoImage = static_cast(image.get()); - - // XXX this is only temporary until we get YUV code in the layer - // system. - videoImage->SetRGBConverter(ToARGBHook); - - OggPlayVideoData* videoData = oggplay_callback_info_get_video_data(aFrame->mVideoHeader); - PlanarYCbCrImage::Data data; - data.mYChannel = videoData->y; - data.mYSize = gfxIntSize(aFrame->mVideoWidth, aFrame->mVideoHeight); - data.mYStride = data.mYSize.width; - data.mCbChannel = videoData->u; - data.mCrChannel = videoData->v; - data.mCbCrSize = gfxIntSize(aFrame->mUVWidth, aFrame->mUVHeight); - data.mCbCrStride = data.mCbCrSize.width; - videoImage->SetData(data); - - mDecoder->SetVideoData(data.mYSize, mAspectRatio, image); - } - - // Don't play the frame's video data more than once. - aFrame->ClearVideoHeader(); - } -} - -void nsOggDecodeStateMachine::PlayAudio(FrameData* aFrame) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (!mAudioStream) - return; - - aFrame->Write(mAudioStream); -} - -void nsOggDecodeStateMachine::OpenAudioStream() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mAudioStream = new nsAudioStream(); - if (!mAudioStream) { - LOG(PR_LOG_ERROR, ("%p Could not create audio stream", mDecoder)); - } - else { - mAudioStream->Init(mAudioChannels, mAudioRate, nsAudioStream::FORMAT_FLOAT32); - mAudioStream->SetVolume(mVolume); - } -} - -void nsOggDecodeStateMachine::CloseAudioStream() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (mAudioStream) { - mAudioStream->Shutdown(); - mAudioStream = nsnull; - } -} - -void nsOggDecodeStateMachine::StartAudio() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (HasAudio()) { - OpenAudioStream(); - } -} - -void nsOggDecodeStateMachine::StopAudio() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (HasAudio()) { - CloseAudioStream(); - } -} - -void nsOggDecodeStateMachine::StartPlayback() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - StartAudio(); - mPlaying = PR_TRUE; - - // If this is the very first play, then set the initial start time - if (mPlayStartTime.IsNull()) { - mPlayStartTime = TimeStamp::Now(); - } - - // If we have been paused previously, then compute duration spent paused - if (!mPauseStartTime.IsNull()) { - mPauseDuration += TimeStamp::Now() - mPauseStartTime; - // Null out mPauseStartTime - mPauseStartTime = TimeStamp(); - } -} - -void nsOggDecodeStateMachine::StopPlayback() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mLastFrame = mDecodedFrames.ResetTimes(mCallbackPeriod); - StopAudio(); - mPlaying = PR_FALSE; - mPauseStartTime = TimeStamp(); - mPauseDuration = 0; - mPlayStartTime = TimeStamp(); -} - -void nsOggDecodeStateMachine::PausePlayback() -{ - if (!mAudioStream) { - StopPlayback(); - return; - } - mAudioStream->Pause(); - mPlaying = PR_FALSE; - mPauseStartTime = TimeStamp::Now(); -} - -void nsOggDecodeStateMachine::ResumePlayback() -{ - if (!mAudioStream) { - StartPlayback(); - return; - } - - mAudioStream->Resume(); - mPlaying = PR_TRUE; - - // Compute duration spent paused - if (!mPauseStartTime.IsNull()) { - mPauseDuration += TimeStamp::Now() - mPauseStartTime; - // Null out mPauseStartTime - mPauseStartTime = TimeStamp(); - } -} - -void nsOggDecodeStateMachine::UpdatePlaybackPosition(float aTime) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mCurrentFrameTime = aTime - mPlaybackStartTime; - if (!mPositionChangeQueued) { - mPositionChangeQueued = PR_TRUE; - nsCOMPtr event = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackPositionChanged); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); - } -} - -void nsOggDecodeStateMachine::QueueDecodedFrames() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - FrameData* frame; - while (!mDecodedFrames.IsFull() && (frame = NextFrame())) { - PRUint32 oldFrameCount = mDecodedFrames.GetCount(); - mDecodedFrames.Push(frame); - if (oldFrameCount < 2) { - // Transitioning from 0 to 1 frames or from 1 to 2 frames could - // affect HaveNextFrameData and hence what UpdateReadyStateForData does. - // This could change us from HAVE_CURRENT_DATA to HAVE_FUTURE_DATA - // (or even HAVE_ENOUGH_DATA), so we'd better trigger an - // update to the ready state. - UpdateReadyState(); - } - } -} - -void nsOggDecodeStateMachine::ClearPositionChangeFlag() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mPositionChangeQueued = PR_FALSE; -} - -nsHTMLMediaElement::NextFrameStatus nsOggDecodeStateMachine::GetNextFrameStatus() -{ - nsAutoMonitor mon(mDecoder->GetMonitor()); - if (IsBuffering() || IsSeeking()) { - return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING; - } else if (HaveNextFrameData()) { - return nsHTMLMediaElement::NEXT_FRAME_AVAILABLE; - } - return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE; -} - -void nsOggDecodeStateMachine::SetVolume(float volume) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (mAudioStream) { - mAudioStream->SetVolume(volume); - } - - mVolume = volume; -} - -float nsOggDecodeStateMachine::GetCurrentTime() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mCurrentFrameTime; -} - -PRInt64 nsOggDecodeStateMachine::GetDuration() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mDuration; -} - -void nsOggDecodeStateMachine::SetDuration(PRInt64 aDuration) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mDuration = aDuration; -} - -void nsOggDecodeStateMachine::SetSeekable(PRBool aSeekable) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mSeekable = aSeekable; -} - -void nsOggDecodeStateMachine::Shutdown() -{ - // oggplay_prepare_for_close cannot be undone. Once called, the - // mPlayer object cannot decode any more frames. Once we've entered - // the shutdown state here there's no going back. - nsAutoMonitor mon(mDecoder->GetMonitor()); - - // Change state before issuing shutdown request to threads so those - // threads can start exiting cleanly during the Shutdown call. - LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN", mDecoder)); - mState = DECODER_STATE_SHUTDOWN; - mon.NotifyAll(); - - if (mPlayer) { - // This will unblock the step decode loop in the - // StepDecode thread. The thread can then be safely - // shutdown. - oggplay_prepare_for_close(mPlayer); - } -} - -void nsOggDecodeStateMachine::Decode() -{ - // When asked to decode, switch to decoding only if - // we are currently buffering. - nsAutoMonitor mon(mDecoder->GetMonitor()); - if (mState == DECODER_STATE_BUFFERING) { - LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); - mState = DECODER_STATE_DECODING; - mon.NotifyAll(); - } -} - -void nsOggDecodeStateMachine::Seek(float aTime) -{ - nsAutoMonitor mon(mDecoder->GetMonitor()); - // nsOggDecoder::mPlayState should be SEEKING while we seek, and - // in that case nsOggDecoder shouldn't be calling us. - NS_ASSERTION(mState != DECODER_STATE_SEEKING, - "We shouldn't already be seeking"); - mSeekTime = aTime + mPlaybackStartTime; - float duration = static_cast(mDuration) / 1000.0; - NS_ASSERTION(mSeekTime >= 0 && mSeekTime <= duration, - "Can only seek in range [0,duration]"); - LOG(PR_LOG_DEBUG, ("%p Changed state to SEEKING (to %f)", mDecoder, aTime)); - mState = DECODER_STATE_SEEKING; -} - -class ByteRange { -public: - ByteRange() : mStart(-1), mEnd(-1) {} - ByteRange(PRInt64 aStart, PRInt64 aEnd) : mStart(aStart), mEnd(aEnd) {} - PRInt64 mStart, mEnd; -}; - -static void GetBufferedBytes(nsMediaStream* aStream, nsTArray& aRanges) -{ - PRInt64 startOffset = 0; - while (PR_TRUE) { - PRInt64 endOffset = aStream->GetCachedDataEnd(startOffset); - if (endOffset == startOffset) { - // Uncached at startOffset. - endOffset = aStream->GetNextCachedData(startOffset); - if (endOffset == -1) { - // Uncached at startOffset until endOffset of stream, or we're at - // the end of stream. - break; - } - } else { - // Bytes [startOffset..endOffset] are cached. - PRInt64 cachedLength = endOffset - startOffset; - // Only bother trying to seek inside ranges greater than - // MIN_BOUNDED_SEEK_SIZE, so that the bounded seek is unlikely to - // read outside of the range when finding Ogg page boundaries. - if (cachedLength > MIN_BOUNDED_SEEK_SIZE) { - aRanges.AppendElement(ByteRange(startOffset, endOffset)); - } - } - startOffset = endOffset; - } -} - -nsresult nsOggDecodeStateMachine::Seek(float aTime, nsChannelReader* aReader) -{ - LOG(PR_LOG_DEBUG, ("%p About to seek OggPlay to %fms", mDecoder, aTime)); - nsMediaStream* stream = aReader->Stream(); - nsAutoTArray ranges; - stream->Pin(); - GetBufferedBytes(stream, ranges); - PRInt64 rv = -1; - for (PRUint32 i = 0; rv < 0 && i < ranges.Length(); i++) { - rv = oggplay_seek_to_keyframe(mPlayer, - ogg_int64_t(aTime * 1000), - ranges[i].mStart, - ranges[i].mEnd); - } - stream->Unpin(); - - if (rv < 0) { - // Could not seek in a buffered range, fall back to seeking over the - // entire media. - rv = oggplay_seek_to_keyframe(mPlayer, - ogg_int64_t(aTime * 1000), - 0, - stream->GetLength()); - } - - LOG(PR_LOG_DEBUG, ("%p Finished seeking OggPlay", mDecoder)); - - return (rv < 0) ? NS_ERROR_FAILURE : NS_OK; -} - -PRBool nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor, - float aTime) -{ - // Drop frames before the target time. - float target = aTime - mCallbackPeriod / 2.0; - FrameData* frame = nsnull; - OggPlayErrorCode r; - mLastFrame = 0; - - // Some of the audio data from previous frames actually belongs - // to this frame and later frames. So rescue that data and stuff - // it into the first frame. - float audioTime = 0; - nsTArray audioData; - do { - if (frame) { - audioData.AppendElements(frame->mAudioData); - audioTime += frame->mAudioData.Length() / - (float)mAudioRate / (float)mAudioChannels; - } - do { - aMonitor.Exit(); - r = DecodeFrame(); - aMonitor.Enter(); - } while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT); - - HandleDecodeErrors(r); - - if (mState == DECODER_STATE_SHUTDOWN) - break; - - FrameData* nextFrame = NextFrame(); - if (!nextFrame) - break; - - delete frame; - frame = nextFrame; - } while (frame->mDecodedFrameTime < target); - - if (mState == DECODER_STATE_SHUTDOWN) { - delete frame; - return PR_TRUE; - } - - NS_ASSERTION(frame != nsnull, "No frame after decode!"); - if (frame) { - if (audioTime > frame->mTime) { - // liboggplay gave us more data than expected, we need to prepend - // the extra data to the current frame to keep audio in sync. - audioTime -= frame->mTime; - // numExtraSamples must be evenly divisble by number of channels. - size_t numExtraSamples = mAudioChannels * - PRInt32(NS_ceil(mAudioRate*audioTime)); - float* data = audioData.Elements() + audioData.Length() - numExtraSamples; - float* dst = frame->mAudioData.InsertElementsAt(0, numExtraSamples); - memcpy(dst, data, numExtraSamples * sizeof(float)); - } - - mLastFrame = 0; - frame->mTime = 0; - frame->mState = OGGPLAY_STREAM_JUST_SEEKED; - mDecodedFrames.Push(frame); - UpdatePlaybackPosition(frame->mDecodedFrameTime); - PlayVideo(frame); - } - - return r == E_OGGPLAY_OK; -} - -void nsOggDecodeStateMachine::StopStepDecodeThread(nsAutoMonitor* aMonitor) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - - if (!mStepDecodeThread) - return; - - if (!mDecodingCompleted) { - // Break the step-decode thread out of the decoding loop. First - // set the exit flag so it will exit the loop. - mExitStepDecodeThread = PR_TRUE; - // Remove liboggplay frame buffer so that the step-decode thread - // can unblock in liboggplay. - delete NextFrame(); - // Now notify to wake it up if it's waiting on the monitor. - aMonitor->NotifyAll(); - } - - aMonitor->Exit(); - mStepDecodeThread->Shutdown(); - aMonitor->Enter(); - mStepDecodeThread = nsnull; -} - -nsresult nsOggDecodeStateMachine::Run() -{ - nsChannelReader* reader = mDecoder->GetReader(); - NS_ENSURE_TRUE(reader, NS_ERROR_NULL_POINTER); - while (PR_TRUE) { - nsAutoMonitor mon(mDecoder->GetMonitor()); - switch(mState) { - case DECODER_STATE_SHUTDOWN: - if (mPlaying) { - StopPlayback(); - } - StopStepDecodeThread(&mon); - NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN, - "How did we escape from the shutdown state???"); - return NS_OK; - - case DECODER_STATE_DECODING_METADATA: - { - mon.Exit(); - LoadOggHeaders(reader); - mon.Enter(); - - OggPlayErrorCode r = E_OGGPLAY_TIMEOUT; - while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT) { - mon.Exit(); - r = DecodeFrame(); - mon.Enter(); - } - - HandleDecodeErrors(r); - - if (mState == DECODER_STATE_SHUTDOWN) - continue; - - mLastFrame = 0; - FrameData* frame = NextFrame(); - if (frame) { - mDecodedFrames.Push(frame); - mDecoder->mPlaybackPosition = frame->mEndStreamPosition; - mPlaybackStartTime = frame->mDecodedFrameTime; - UpdatePlaybackPosition(frame->mDecodedFrameTime); - // Now that we know the start offset, we can tell the channel - // reader the last frame time. - if (mGotDurationFromHeader) { - // Duration was in HTTP header, so the last frame time is - // start frame time + duration. - reader->SetLastFrameTime((PRInt64)(mPlaybackStartTime * 1000) + mDuration); - } - else if (mDuration != -1) { - // Got duration by seeking to end and getting timestamp of last - // page; mDuration holds the timestamp of the end of the last page. - reader->SetLastFrameTime(mDuration); - // Duration needs to be corrected so it's the length of media, not - // the last frame's end time. Note mPlaybackStartTime is - // presentation time, which is the start-time of the frame. - mDuration -= (PRInt64)(mPlaybackStartTime * 1000); - } - PlayVideo(frame); - } - - // Inform the element that we've loaded the Ogg metadata and the - // first frame. - nsCOMPtr metadataLoadedEvent = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, MetadataLoaded); - NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); - - if (mState == DECODER_STATE_DECODING_METADATA) { - if (r == E_OGGPLAY_OK) { - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to COMPLETED", mDecoder)); - mState = DECODER_STATE_COMPLETED; - } else { - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder)); - mState = DECODER_STATE_DECODING; - } - } - } - break; - - case DECODER_STATE_DECODING: - { - // If there is no step decode thread, start it. It may not be running - // due to us having completed and then restarted playback, seeking, - // or if this is the initial play. - if (!mStepDecodeThread) { - nsresult rv = NS_NewThread(getter_AddRefs(mStepDecodeThread)); - if (NS_FAILED(rv)) { - mState = DECODER_STATE_SHUTDOWN; - continue; - } - - mBufferExhausted = PR_FALSE; - mDecodingCompleted = PR_FALSE; - mExitStepDecodeThread = PR_FALSE; - nsCOMPtr event = new nsOggStepDecodeEvent(this, mPlayer); - mStepDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL); - } - - // Get the decoded frames and store them in our queue of decoded frames - QueueDecodedFrames(); - while (mDecodedFrames.IsEmpty() && !mDecodingCompleted && - !mBufferExhausted) { - if (mPlaying) { - PausePlayback(); - } - mon.Wait(); - if (mState != DECODER_STATE_DECODING) - break; - QueueDecodedFrames(); - } - - if (mState != DECODER_STATE_DECODING) - continue; - - if (mDecodingCompleted) { - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING to COMPLETED", mDecoder)); - mState = DECODER_STATE_COMPLETED; - StopStepDecodeThread(&mon); - continue; - } - - // Show at least the first frame if we're not playing - // so we have a poster frame on initial load and after seek. - if (!mPlaying && !mDecodedFrames.IsEmpty()) { - PlayVideo(mDecodedFrames.Peek()); - } - - if (mBufferExhausted && - mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING && - !mDecoder->mReader->Stream()->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && - !mDecoder->mReader->Stream()->IsSuspendedByCache()) { - // There is at most one frame in the queue and there's - // more data to load. Let's buffer to make sure we can play a - // decent amount of video in the future. - if (mPlaying) { - PausePlayback(); - } - - // We need to tell the element that buffering has started. - // We can't just directly send an asynchronous runnable that - // eventually fires the "waiting" event. The problem is that - // there might be pending main-thread events, such as "data - // received" notifications, that mean we're not actually still - // buffering by the time this runnable executes. So instead - // we just trigger UpdateReadyStateForData; when it runs, it - // will check the current state and decide whether to tell - // the element we're buffering or not. - UpdateReadyState(); - - mBufferingStart = TimeStamp::Now(); - PRPackedBool reliable; - double playbackRate = mDecoder->ComputePlaybackRate(&reliable); - mBufferingEndOffset = mDecoder->mDecoderPosition + - BUFFERING_RATE(playbackRate) * BUFFERING_WAIT; - mState = DECODER_STATE_BUFFERING; - if (mPlaying) { - PausePlayback(); - } - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING to BUFFERING", mDecoder)); - } else { - if (mBufferExhausted) { - // This will wake up the step decode thread and force it to - // call oggplay_step_decoding at least once. This guarantees - // we make progress. - mBufferExhausted = PR_FALSE; - mon.NotifyAll(); - } - PlayFrame(); - } - } - break; - - case DECODER_STATE_SEEKING: - { - // During the seek, don't have a lock on the decoder state, - // otherwise long seek operations can block the main thread. - // The events dispatched to the main thread are SYNC calls. - // These calls are made outside of the decode monitor lock so - // it is safe for the main thread to makes calls that acquire - // the lock since it won't deadlock. We check the state when - // acquiring the lock again in case shutdown has occurred - // during the time when we didn't have the lock. - StopStepDecodeThread(&mon); - if (mState == DECODER_STATE_SHUTDOWN) - continue; - - float seekTime = mSeekTime; - mDecoder->StopProgressUpdates(); - - StopPlayback(); - - // Remove all frames decoded prior to seek from the queue - while (!mDecodedFrames.IsEmpty()) { - delete mDecodedFrames.Pop(); - } - // SeekingStarted will do a UpdateReadyStateForData which will - // inform the element and its users that we have no frames - // to display - - mon.Exit(); - nsCOMPtr startEvent = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStarted); - NS_DispatchToMainThread(startEvent, NS_DISPATCH_SYNC); - - nsresult res = Seek(seekTime, reader); - - // Reactivate all tracks. Liboggplay deactivates tracks when it - // reads to the end of stream, but they must be reactivated in order - // to start reading from them again. - SetTracksActive(); - - mon.Enter(); - mDecoder->StartProgressUpdates(); - mLastFramePosition = mDecoder->mPlaybackPosition; - if (mState == DECODER_STATE_SHUTDOWN) - continue; - - PRBool atEnd = PR_FALSE; - if (NS_SUCCEEDED(res)) { - atEnd = DecodeToFrame(mon, seekTime); - // mSeekTime should not have changed. While we seek, mPlayState - // should always be PLAY_STATE_SEEKING and no-one will call - // nsOggDecoderStateMachine::Seek. - NS_ASSERTION(seekTime == mSeekTime, "No-one should have changed mSeekTime"); - if (mState == DECODER_STATE_SHUTDOWN) { - continue; - } - - if (!atEnd) { - OggPlayErrorCode r; - // Now try to decode another frame to see if we're at the end. - do { - mon.Exit(); - r = DecodeFrame(); - mon.Enter(); - } while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT); - HandleDecodeErrors(r); - if (mState == DECODER_STATE_SHUTDOWN) - continue; - atEnd = r == E_OGGPLAY_OK; - } - QueueDecodedFrames(); - } - - // Change state to DECODING or COMPLETED now. SeekingStopped will - // call nsOggDecodeStateMachine::Seek to reset our state to SEEKING - // if we need to seek again. - nsCOMPtr stopEvent; - if (!atEnd && mDecodedFrames.GetCount() > 1) { - LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to DECODING", - mDecoder, seekTime)); - stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped); - mState = DECODER_STATE_DECODING; - } else { - LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to COMPLETED", - mDecoder, seekTime)); - stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd); - mState = DECODER_STATE_COMPLETED; - } - mon.NotifyAll(); - - mon.Exit(); - NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC); - mon.Enter(); - } - break; - - case DECODER_STATE_BUFFERING: - { - TimeStamp now = TimeStamp::Now(); - if (now - mBufferingStart < TimeDuration::FromSeconds(BUFFERING_WAIT) && - mDecoder->mReader->Stream()->GetCachedDataEnd(mDecoder->mDecoderPosition) < mBufferingEndOffset && - !mDecoder->mReader->Stream()->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && - !mDecoder->mReader->Stream()->IsSuspendedByCache()) { - LOG(PR_LOG_DEBUG, - ("%p In buffering: buffering data until %d bytes available or %f seconds", mDecoder, - PRUint32(mBufferingEndOffset - mDecoder->mReader->Stream()->GetCachedDataEnd(mDecoder->mDecoderPosition)), - BUFFERING_WAIT - (now - mBufferingStart).ToSeconds())); - mon.Wait(PR_MillisecondsToInterval(1000)); - if (mState == DECODER_STATE_SHUTDOWN) - continue; - } else { - LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); - mState = DECODER_STATE_DECODING; - } - - if (mState != DECODER_STATE_BUFFERING) { - mBufferExhausted = PR_FALSE; - // Notify to allow blocked decoder thread to continue - mon.NotifyAll(); - UpdateReadyState(); - if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { - if (!mPlaying) { - ResumePlayback(); - } - } - } - - break; - } - - case DECODER_STATE_COMPLETED: - { - // Get all the remaining decoded frames in the liboggplay buffer and - // place them in the frame queue. - QueueDecodedFrames(); - - // Play the remaining frames in the frame queue - while (mState == DECODER_STATE_COMPLETED && - !mDecodedFrames.IsEmpty()) { - PlayFrame(); - if (mState == DECODER_STATE_COMPLETED) { - // Wait for the time of one frame so we don't tight loop - // and we need to release the monitor so timeupdate and - // invalidate's on the main thread can occur. - mon.Wait(PR_MillisecondsToInterval(PRInt64(mCallbackPeriod*1000))); - QueueDecodedFrames(); - } - } - - if (mState != DECODER_STATE_COMPLETED) - continue; - - if (mAudioStream) { - mon.Exit(); - LOG(PR_LOG_DEBUG, ("%p Begin nsAudioStream::Drain", mDecoder)); - mAudioStream->Drain(); - LOG(PR_LOG_DEBUG, ("%p End nsAudioStream::Drain", mDecoder)); - mon.Enter(); - - // After the drain call the audio stream is unusable. Close it so that - // next time audio is used a new stream is created. The StopPlayback - // call also resets the playing flag so audio is restarted correctly. - StopPlayback(); - - if (mState != DECODER_STATE_COMPLETED) - continue; - } - - if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { - // We were playing, we need to move the current time to the end of - // media, and send an 'ended' event. - mCurrentFrameTime += mCallbackPeriod; - if (mDuration >= 0) { - mCurrentFrameTime = PR_MAX(mCurrentFrameTime, mDuration / 1000.0); - } - - mon.Exit(); - nsCOMPtr event = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded); - NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); - mon.Enter(); - } - - while (mState == DECODER_STATE_COMPLETED) { - mon.Wait(); - } - } - break; - } - } - - return NS_OK; -} - -// Initialize our OggPlay struct with the specified limit on video size. -static OggPlay* -OggPlayOpen(OggPlayReader* reader, - int max_frame_pixels) -{ - OggPlay *me = NULL; - int r; - - if ((me = oggplay_new_with_reader(reader)) == NULL) { - return NULL; - } - - r = oggplay_set_max_video_frame_pixels(me, max_frame_pixels); - if (r != E_OGGPLAY_OK) { - oggplay_close(me); - return NULL; - } - - do { - r = oggplay_initialise(me, 0); - } while (r == E_OGGPLAY_TIMEOUT); - - if (r != E_OGGPLAY_OK) { - oggplay_close(me); - return NULL; - } - - return me; -} - -void nsOggDecodeStateMachine::LoadOggHeaders(nsChannelReader* aReader) -{ - LOG(PR_LOG_DEBUG, ("%p Loading Ogg Headers", mDecoder)); - mPlayer = OggPlayOpen(aReader, MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT); - if (!mPlayer) { - nsAutoMonitor mon(mDecoder->GetMonitor()); - mState = DECODER_STATE_SHUTDOWN; - HandleDecodeErrors(E_OGGPLAY_UNINITIALISED); - return; - } - LOG(PR_LOG_DEBUG, ("%p There are %d tracks", mDecoder, oggplay_get_num_tracks(mPlayer))); - - for (int i = 0; i < oggplay_get_num_tracks(mPlayer); ++i) { - LOG(PR_LOG_DEBUG, ("%p Tracks %d: %s", mDecoder, i, oggplay_get_track_typename(mPlayer, i))); - if (mVideoTrack == -1 && oggplay_get_track_type(mPlayer, i) == OGGZ_CONTENT_THEORA) { - oggplay_set_callback_num_frames(mPlayer, i, 1); - mVideoTrack = i; - - int fpsd, fpsn; - oggplay_get_video_fps(mPlayer, i, &fpsd, &fpsn); - mFramerate = fpsd == 0 ? 0.0 : float(fpsn)/float(fpsd); - mCallbackPeriod = 1.0 / mFramerate; - LOG(PR_LOG_DEBUG, ("%p Frame rate: %f", mDecoder, mFramerate)); - - int aspectd, aspectn; - // this can return E_OGGPLAY_UNINITIALISED if the video has - // no aspect ratio data. We assume 1.0 in that case. - OggPlayErrorCode r = - oggplay_get_video_aspect_ratio(mPlayer, i, &aspectd, &aspectn); - mAspectRatio = r == E_OGGPLAY_OK && aspectd > 0 ? - float(aspectn)/float(aspectd) : 1.0; - - int y_width; - int y_height; - oggplay_get_video_y_size(mPlayer, i, &y_width, &y_height); - mDecoder->SetVideoData(gfxIntSize(y_width, y_height), mAspectRatio, - nsnull); - } - else if (mAudioTrack == -1 && oggplay_get_track_type(mPlayer, i) == OGGZ_CONTENT_VORBIS) { - mAudioTrack = i; - oggplay_set_offset(mPlayer, i, OGGPLAY_AUDIO_OFFSET); - oggplay_get_audio_samplerate(mPlayer, i, &mAudioRate); - oggplay_get_audio_channels(mPlayer, i, &mAudioChannels); - LOG(PR_LOG_DEBUG, ("%p samplerate: %d, channels: %d", mDecoder, mAudioRate, mAudioChannels)); - } - } - - if (mVideoTrack == -1 && mAudioTrack == -1) { - nsAutoMonitor mon(mDecoder->GetMonitor()); - HandleDecodeErrors(E_OGGPLAY_UNINITIALISED); - return; - } - - SetTracksActive(); - - if (mVideoTrack == -1) { - oggplay_set_callback_num_frames(mPlayer, mAudioTrack, OGGPLAY_FRAMES_PER_CALLBACK); - mCallbackPeriod = 1.0 / (float(mAudioRate) / OGGPLAY_FRAMES_PER_CALLBACK); - } - LOG(PR_LOG_DEBUG, ("%p Callback Period: %f", mDecoder, mCallbackPeriod)); - - oggplay_use_buffer(mPlayer, OGGPLAY_BUFFER_SIZE); - - // Get the duration from the Ogg file. We only do this if the - // content length of the resource is known as we need to seek - // to the end of the file to get the last time field. We also - // only do this if the resource is seekable and if we haven't - // already obtained the duration via an HTTP header. - { - nsAutoMonitor mon(mDecoder->GetMonitor()); - mGotDurationFromHeader = (mDuration != -1); - if (mState != DECODER_STATE_SHUTDOWN && - aReader->Stream()->GetLength() >= 0 && - mSeekable && - mDuration == -1) { - mDecoder->StopProgressUpdates(); - // Don't hold the monitor during the duration - // call as it can issue seek requests - // and blocks until these are completed. - mon.Exit(); - PRInt64 d = oggplay_get_duration(mPlayer); - oggplay_seek(mPlayer, 0); - mon.Enter(); - mDuration = d; - mDecoder->StartProgressUpdates(); - mDecoder->UpdatePlaybackRate(); - } - if (mState == DECODER_STATE_SHUTDOWN) - return; - } -} - -void nsOggDecodeStateMachine::SetTracksActive() -{ - if (mVideoTrack != -1 && - oggplay_set_track_active(mPlayer, mVideoTrack) < 0) { - LOG(PR_LOG_ERROR, ("%p Could not set track %d active", mDecoder, mVideoTrack)); - } - - if (mAudioTrack != -1 && - oggplay_set_track_active(mPlayer, mAudioTrack) < 0) { - LOG(PR_LOG_ERROR, ("%p Could not set track %d active", mDecoder, mAudioTrack)); - } -} - NS_IMPL_THREADSAFE_ISUPPORTS1(nsOggDecoder, nsIObserver) void nsOggDecoder::Pause() { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (mPlayState == PLAY_STATE_SEEKING || mPlayState == PLAY_STATE_ENDED) { mNextState = PLAY_STATE_PAUSED; return; @@ -1985,9 +72,8 @@ void nsOggDecoder::Pause() void nsOggDecoder::SetVolume(float volume) { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); mInitialVolume = volume; - if (mDecodeStateMachine) { mDecodeStateMachine->SetVolume(volume); } @@ -1995,15 +81,15 @@ void nsOggDecoder::SetVolume(float volume) float nsOggDecoder::GetDuration() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mDuration >= 0) { return static_cast(mDuration) / 1000.0; } - return std::numeric_limits::quiet_NaN(); } nsOggDecoder::nsOggDecoder() : - nsMediaDecoder(), + mMonitor("media.decoder"), mDecoderPosition(0), mPlaybackPosition(0), mCurrentTime(0.0), @@ -2011,15 +97,13 @@ nsOggDecoder::nsOggDecoder() : mRequestedSeekTime(-1.0), mDuration(-1), mSeekable(PR_TRUE), - mReader(nsnull), - mMonitor(nsnull), mPlayState(PLAY_STATE_PAUSED), mNextState(PLAY_STATE_PAUSED), mResourceLoaded(PR_FALSE), mIgnoreProgressData(PR_FALSE) { MOZ_COUNT_CTOR(nsOggDecoder); - + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); #ifdef PR_LOGGING if (!gOggDecoderLog) { gOggDecoderLog = PR_NewLogModule("nsOggDecoder"); @@ -2029,42 +113,32 @@ nsOggDecoder::nsOggDecoder() : PRBool nsOggDecoder::Init(nsHTMLMediaElement* aElement) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (!nsMediaDecoder::Init(aElement)) return PR_FALSE; - mMonitor = nsAutoMonitor::NewMonitor("media.decoder"); - if (!mMonitor) - return PR_FALSE; - nsContentUtils::RegisterShutdownObserver(this); - - mReader = new nsChannelReader(); - NS_ENSURE_TRUE(mReader, PR_FALSE); - mImageContainer = aElement->GetImageContainer(); - return PR_TRUE; } void nsOggDecoder::Stop() { - NS_ASSERTION(NS_IsMainThread(), "Should be called on main thread"); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread"); // The decode thread must die before the state machine can die. // The state machine must die before the reader. // The state machine must die before the decoder. - if (mDecodeThread) - mDecodeThread->Shutdown(); + if (mStateMachineThread) + mStateMachineThread->Shutdown(); - mDecodeThread = nsnull; + mStateMachineThread = nsnull; mDecodeStateMachine = nsnull; - mReader = nsnull; } void nsOggDecoder::Shutdown() { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::Shutdown called on non-main thread"); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2080,14 +154,14 @@ void nsOggDecoder::Shutdown() // Force any outstanding seek and byterange requests to complete // to prevent shutdown from deadlocking. - if (mReader) { - mReader->Stream()->Close(); + if (mStream) { + mStream->Close(); } ChangeState(PLAY_STATE_SHUTDOWN); nsMediaDecoder::Shutdown(); - // We can't destroy mDecodeStateMachine until mDecodeThread is shut down. + // We can't destroy mDecodeStateMachine until mStateMachineThread is shut down. // It's unsafe to Shutdown() the decode thread here, as // nsIThread::Shutdown() may run events, such as JS event handlers, // and we could be running at an unsafe time such as during element @@ -2103,13 +177,14 @@ void nsOggDecoder::Shutdown() nsOggDecoder::~nsOggDecoder() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); MOZ_COUNT_DTOR(nsOggDecoder); - nsAutoMonitor::DestroyMonitor(mMonitor); } nsresult nsOggDecoder::Load(nsMediaStream* aStream, nsIStreamListener** aStreamListener) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (aStreamListener) { *aStreamListener = nsnull; } @@ -2118,7 +193,7 @@ nsresult nsOggDecoder::Load(nsMediaStream* aStream, // Hold the lock while we do this to set proper lock ordering // expectations for dynamic deadlock detectors: decoder lock(s) // should be grabbed before the cache lock - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); nsresult rv = aStream->Open(aStreamListener); if (NS_FAILED(rv)) { @@ -2126,27 +201,31 @@ nsresult nsOggDecoder::Load(nsMediaStream* aStream, return rv; } - mReader->Init(aStream); + mStream = aStream; } - nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread)); + nsresult rv = NS_NewThread(getter_AddRefs(mStateMachineThread)); NS_ENSURE_SUCCESS(rv, rv); - mDecodeStateMachine = new nsOggDecodeStateMachine(this); + mDecodeStateMachine = new nsOggPlayStateMachine(this); + if (NS_FAILED(mDecodeStateMachine->Init())) { + return NS_ERROR_FAILURE; + } { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDecodeStateMachine->SetSeekable(mSeekable); mDecodeStateMachine->SetDuration(mDuration); } ChangeState(PLAY_STATE_LOADING); - return mDecodeThread->Dispatch(mDecodeStateMachine, NS_DISPATCH_NORMAL); + return mStateMachineThread->Dispatch(mDecodeStateMachine, NS_DISPATCH_NORMAL); } nsresult nsOggDecoder::Play() { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (mPlayState == PLAY_STATE_SEEKING) { mNextState = PLAY_STATE_PLAYING; return NS_OK; @@ -2161,7 +240,8 @@ nsresult nsOggDecoder::Play() nsresult nsOggDecoder::Seek(float aTime) { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (aTime < 0.0) return NS_ERROR_FAILURE; @@ -2185,28 +265,31 @@ nsresult nsOggDecoder::Seek(float aTime) nsresult nsOggDecoder::PlaybackRateChanged() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); return NS_ERROR_NOT_IMPLEMENTED; } float nsOggDecoder::GetCurrentTime() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); return mCurrentTime; } nsMediaStream* nsOggDecoder::GetCurrentStream() { - return mReader ? mReader->Stream() : nsnull; + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + return mStream; } already_AddRefed nsOggDecoder::GetCurrentPrincipal() { - if (!mReader) - return nsnull; - return mReader->Stream()->GetCurrentPrincipal(); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + return mStream ? mStream->GetCurrentPrincipal() : nsnull; } void nsOggDecoder::MetadataLoaded() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2214,7 +297,7 @@ void nsOggDecoder::MetadataLoaded() // to fulfill a seek, otherwise we'll get multiple metadataloaded events. PRBool notifyElement = PR_TRUE; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDuration = mDecodeStateMachine ? mDecodeStateMachine->GetDuration() : -1; notifyElement = mNextState != PLAY_STATE_SEEKING; } @@ -2228,32 +311,29 @@ void nsOggDecoder::MetadataLoaded() if (!mResourceLoaded) { StartProgress(); - } - else if (mElement) - { + } else if (mElement) { // Resource was loaded during metadata loading, when progress // events are being ignored. Fire the final progress event. mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); } - + // Only inform the element of FirstFrameLoaded if not doing a load() in order // to fulfill a seek, otherwise we'll get multiple loadedfirstframe events. - PRBool resourceIsLoaded = !mResourceLoaded && mReader && - mReader->Stream()->IsDataCachedToEndOfStream(mDecoderPosition); + PRBool resourceIsLoaded = !mResourceLoaded && mStream && + mStream->IsDataCachedToEndOfStream(mDecoderPosition); if (mElement && notifyElement) { mElement->FirstFrameLoaded(resourceIsLoaded); } // The element can run javascript via events - // before reaching here, so only change the + // before reaching here, so only change the // state if we're still set to the original // loading state. - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); if (mPlayState == PLAY_STATE_LOADING) { if (mRequestedSeekTime >= 0.0) { ChangeState(PLAY_STATE_SEEKING); - } - else { + } else { ChangeState(mNextState); } } @@ -2265,6 +345,8 @@ void nsOggDecoder::MetadataLoaded() void nsOggDecoder::ResourceLoaded() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + // Don't handle ResourceLoaded if we are shutting down, or if // we need to ignore progress data due to seeking (in the case // that the seek results in reaching end of file, we get a bogus call @@ -2275,7 +357,7 @@ void nsOggDecoder::ResourceLoaded() { // If we are seeking or loading then the resource loaded notification we get // should be ignored, since it represents the end of the seek request. - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); if (mIgnoreProgressData || mResourceLoaded || mPlayState == PLAY_STATE_LOADING) return; @@ -2294,6 +376,7 @@ void nsOggDecoder::ResourceLoaded() void nsOggDecoder::NetworkError() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2305,6 +388,7 @@ void nsOggDecoder::NetworkError() void nsOggDecoder::DecodeError() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2342,6 +426,7 @@ NS_IMETHODIMP nsOggDecoder::Observe(nsISupports *aSubjet, const char *aTopic, const PRUnichar *someData) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { Shutdown(); } @@ -2352,15 +437,16 @@ NS_IMETHODIMP nsOggDecoder::Observe(nsISupports *aSubjet, nsMediaDecoder::Statistics nsOggDecoder::GetStatistics() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); Statistics result; - nsAutoMonitor mon(mMonitor); - if (mReader) { + MonitorAutoEnter mon(mMonitor); + if (mStream) { result.mDownloadRate = - mReader->Stream()->GetDownloadRate(&result.mDownloadRateReliable); + mStream->GetDownloadRate(&result.mDownloadRateReliable); result.mDownloadPosition = - mReader->Stream()->GetCachedDataEnd(mDecoderPosition); - result.mTotalBytes = mReader->Stream()->GetLength(); + mStream->GetCachedDataEnd(mDecoderPosition); + result.mTotalBytes = mStream->GetLength(); result.mPlaybackRate = ComputePlaybackRate(&result.mPlaybackRateReliable); result.mDecoderPosition = mDecoderPosition; result.mPlaybackPosition = mPlaybackPosition; @@ -2380,7 +466,11 @@ nsOggDecoder::GetStatistics() double nsOggDecoder::ComputePlaybackRate(PRPackedBool* aReliable) { - PRInt64 length = mReader ? mReader->Stream()->GetLength() : -1; + GetMonitor().AssertCurrentThreadIn(); + NS_ASSERTION(NS_IsMainThread() || IsThread(mStateMachineThread), + "Should be on main or state machine thread."); + + PRInt64 length = mStream ? mStream->GetLength() : -1; if (mDuration >= 0 && length >= 0) { *aReliable = PR_TRUE; return double(length)*1000.0/mDuration; @@ -2390,28 +480,30 @@ double nsOggDecoder::ComputePlaybackRate(PRPackedBool* aReliable) void nsOggDecoder::UpdatePlaybackRate() { - if (!mReader) + NS_ASSERTION(NS_IsMainThread() || IsThread(mStateMachineThread), + "Should be on main or state machine thread."); + GetMonitor().AssertCurrentThreadIn(); + if (!mStream) return; PRPackedBool reliable; PRUint32 rate = PRUint32(ComputePlaybackRate(&reliable)); if (reliable) { // Avoid passing a zero rate - rate = PR_MAX(rate, 1); + rate = NS_MAX(rate, 1u); } else { // Set a minimum rate of 10,000 bytes per second ... sometimes we just // don't have good data - rate = PR_MAX(rate, 10000); + rate = NS_MAX(rate, 10000u); } - mReader->Stream()->SetPlaybackRate(rate); + mStream->SetPlaybackRate(rate); } void nsOggDecoder::NotifySuspendedStatusChanged() { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::NotifyDownloadSuspended called on non-main thread"); - if (!mReader) + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (!mStream) return; - if (mReader->Stream()->IsSuspendedByCache() && mElement) { + if (mStream->IsSuspendedByCache() && mElement) { // if this is an autoplay element, we need to kick off its autoplaying // now so we consume data and hopefully free up cache space mElement->NotifyAutoplayDataReady(); @@ -2420,19 +512,20 @@ void nsOggDecoder::NotifySuspendedStatusChanged() void nsOggDecoder::NotifyBytesDownloaded() { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::NotifyBytesDownloaded called on non-main thread"); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); UpdateReadyStateForData(); Progress(PR_FALSE); } void nsOggDecoder::NotifyDownloadEnded(nsresult aStatus) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (aStatus == NS_BINDING_ABORTED) return; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); UpdatePlaybackRate(); } @@ -2446,7 +539,9 @@ void nsOggDecoder::NotifyDownloadEnded(nsresult aStatus) void nsOggDecoder::NotifyBytesConsumed(PRInt64 aBytes) { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mDecodeStateMachine->OnStateMachineThread() || mDecodeStateMachine->OnDecodeThread(), + "Should be on play state machine or decode thread."); if (!mIgnoreProgressData) { mDecoderPosition += aBytes; } @@ -2492,11 +587,13 @@ void nsOggDecoder::UpdateReadyStateForData() void nsOggDecoder::SeekingStopped() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mShuttingDown) return; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); // An additional seek was requested while the current seek was // in operation. @@ -2516,12 +613,14 @@ void nsOggDecoder::SeekingStopped() // media. void nsOggDecoder::SeekingStoppedAtEnd() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mShuttingDown) return; PRBool fireEnded = PR_FALSE; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); // An additional seek was requested while the current seek was // in operation. @@ -2544,6 +643,7 @@ void nsOggDecoder::SeekingStoppedAtEnd() void nsOggDecoder::SeekingStarted() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2555,16 +655,15 @@ void nsOggDecoder::SeekingStarted() void nsOggDecoder::ChangeState(PlayState aState) { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::ChangeState called on non-main thread"); - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (mNextState == aState) { mNextState = PLAY_STATE_PAUSED; } if (mPlayState == PLAY_STATE_SHUTDOWN) { - mon.NotifyAll(); + mMonitor.NotifyAll(); return; } @@ -2593,11 +692,12 @@ void nsOggDecoder::ChangeState(PlayState aState) /* No action needed */ break; } - mon.NotifyAll(); + mMonitor.NotifyAll(); } void nsOggDecoder::PlaybackPositionChanged() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2606,7 +706,7 @@ void nsOggDecoder::PlaybackPositionChanged() // Control the scope of the monitor so it is not // held while the timeupdate and the invalidate is run. { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); if (mDecodeStateMachine) { mCurrentTime = mDecodeStateMachine->GetCurrentTime(); @@ -2625,11 +725,24 @@ void nsOggDecoder::PlaybackPositionChanged() } } +void nsOggDecoder::DurationChanged() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); + PRInt64 oldDuration = mDuration; + mDuration = mDecodeStateMachine ? mDecodeStateMachine->GetDuration() : -1; + if (mElement && oldDuration != mDuration) { + LOG(PR_LOG_DEBUG, ("%p duration changed to %lldms", this, mDuration)); + mElement->DispatchSimpleEvent(NS_LITERAL_STRING("durationchange")); + } +} + void nsOggDecoder::SetDuration(PRInt64 aDuration) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); mDuration = aDuration; if (mDecodeStateMachine) { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDecodeStateMachine->SetDuration(mDuration); UpdatePlaybackRate(); } @@ -2637,53 +750,59 @@ void nsOggDecoder::SetDuration(PRInt64 aDuration) void nsOggDecoder::SetSeekable(PRBool aSeekable) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); mSeekable = aSeekable; if (mDecodeStateMachine) { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDecodeStateMachine->SetSeekable(aSeekable); } } PRBool nsOggDecoder::GetSeekable() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); return mSeekable; } void nsOggDecoder::Suspend() { - if (mReader) { - mReader->Stream()->Suspend(PR_TRUE); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mStream) { + mStream->Suspend(PR_TRUE); } } void nsOggDecoder::Resume() { - if (mReader) { - mReader->Stream()->Resume(); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mStream) { + mStream->Resume(); } } void nsOggDecoder::StopProgressUpdates() { + NS_ASSERTION(IsThread(mStateMachineThread), "Should be on state machine thread."); mIgnoreProgressData = PR_TRUE; - if (mReader) { - mReader->Stream()->SetReadMode(nsMediaCacheStream::MODE_METADATA); + if (mStream) { + mStream->SetReadMode(nsMediaCacheStream::MODE_METADATA); } } void nsOggDecoder::StartProgressUpdates() { + NS_ASSERTION(IsThread(mStateMachineThread), "Should be on state machine thread."); mIgnoreProgressData = PR_FALSE; - if (mReader) { - mReader->Stream()->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK); - mDecoderPosition = mPlaybackPosition = mReader->Stream()->Tell(); + if (mStream) { + mStream->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK); + mDecoderPosition = mPlaybackPosition = mStream->Tell(); } } void nsOggDecoder::MoveLoadsToBackground() { - if (mReader) { - mReader->Stream()->MoveLoadsToBackground(); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mStream) { + mStream->MoveLoadsToBackground(); } } - diff --git a/content/media/ogg/nsOggDecoder.h b/content/media/ogg/nsOggDecoder.h index 3eaba0836103..4f5c74b05b30 100644 --- a/content/media/ogg/nsOggDecoder.h +++ b/content/media/ogg/nsOggDecoder.h @@ -21,6 +21,7 @@ * * Contributor(s): * Chris Double + * Chris Pearce * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,55 +37,67 @@ * * ***** END LICENSE BLOCK ***** */ /* -Each video element has two threads. The first thread, called the Decode thread, -owns the resources for downloading and reading the video file. It goes through the -file, prcessing any decoded theora and vorbis data. It handles the sending of the -audio data to the sound device and the presentation of the video data at the correct -frame rate. +Each video element has three threads. -The second thread is the step decode thread. It uses OggPlay to decode the video and -audio data. It indirectly uses an nsMediaStream to do the file reading and seeking via -Oggplay. + 1) The state machine thread owns the resources for downloading and reading + the media file. It controls the lifetime of the other two threads + and renders the video data at the correct time during playback. -All file reads and seeks must occur on these two threads. Synchronisation is done via -liboggplay internal mutexes to ensure that access to the liboggplay structures is -done correctly in the presence of the threads. + 2) The Audio thread writes the decoded audio data to the audio + hardware. This is done in a seperate thread to ensure that the + audio hardware gets a constant stream of data without + interruption due to decoding or diplay. At some point + libsydneyaudio will be refactored to have a callback interface + where it asks for data and an extra thread will no longer be + needed. -The step decode thread is created and destroyed in the decode thread. When decoding -needs to be done it is created and event dispatched to it to start the decode loop. -This event exits when decoding is completed or no longer required (during seeking -or shutdown). + 3) The decode thread. This thread reads from the media stream and decodes + the Theora and Vorbis data. It places the decoded data in a queue + for the other threads to pull from. + +All file reads and seeks must occur on either the state machine thread +or the decode thread. Synchronisation is done via a monitor owned by +nsOggDecoder. + +The decode thread and the audio thread are created and destroyed in the +state machine thread. When playback needs to occur they are created and +events dispatched to them to start them. These events exit when +decoding is completed or no longer required (during seeking or +shutdown). -When the decode thread is created an event is dispatched to it. The event -runs for the lifetime of the playback of the resource. The decode thread -synchronises with the main thread via a single monitor held by the -nsOggDecoder object. +All threads have one event that is dispatched to it and that event +runs for the lifetime of the playback of the resource. State shared +between them is synchronised with the main thread via a monitor +held by the nsOggDecoder object. The decode thread also has its own +monitor to ensure that its internal state is independent of the other +threads, and to ensure that it's not hogging the monitor while decoding. -The event contains a Run method which consists of an infinite loop -that checks the state that the state machine is in and processes -operations on that state. +The events consist of a Run method which is an infinite loop that +perform the threads operation and checks the state that the state +machine is in and processes operations on that state. -The nsOggDecodeStateMachine class is the event that gets dispatched to -the decode thread. It has the following states: +The nsOggPlayStateMachine class is the event that gets dispatched to +the state machine thread. It has the following states: DECODING_METADATA The Ogg headers are being loaded, and things like framerate, etc are being determined, and the first frame of audio/video data is being decoded. DECODING - Video/Audio frames are being decoded. + The decode and audio threads are started and video frames displayed at + the required time. SEEKING A seek operation is in progress. BUFFERING Decoding is paused while data is buffered for smooth playback. COMPLETED - The resource has completed decoding. + The resource has completed decoding, but not finished playback. SHUTDOWN The decoder object is about to be destroyed. The following result in state transitions. Shutdown() - Clean up any resources the nsOggDecodeStateMachine owns. + Clean up any resources the nsOggPlayStateMachine owns. Decode() Start decoding video frames. Buffer @@ -163,7 +176,7 @@ player SHUTDOWN decoder SHUTDOWN The general sequence of events with these objects is: 1) The video element calls Load on nsMediaDecoder. This creates the - decode thread and starts the channel for downloading the file. It + state machine thread and starts the channel for downloading the file. It instantiates and starts the Decode state machine. The high level LOADING state is entered, which results in the decode state machine to start decoding metadata. These are the headers that give the @@ -188,66 +201,52 @@ The general sequence of events with these objects is: video, if the correct frame time comes around and the decoder play state is PLAYING. -a/v synchronisation is done by a combination of liboggplay and the -Decoder state machine. liboggplay ensures that a decoded frame of data -has both the audio samples and the YUV data for that period of time. +a/v synchronisation is handled by the stete machine thread. It examines the +audio playback time and compares this to the next frame in the queue +of frames. If it is time to play the video frame it is then displayed. -When a frame is decoded by the decode state machine it converts the -YUV encoded video to RGB and copies the sound data to an internal -FrameData object. This is stored in a queue of available decoded frames. -Included in the FrameData object is the time that that frame should -be displayed. +Frame skipping is done in the following ways: -The display state machine keeps track of the time since the last frame it -played. After decoding a frame it checks if it is time to display the next -item in the decoded frame queue. If so, it pops the item off the queue -and displays it. + 1) The state machine thread will skip all frames in the video queue whose + display time is less than the current audio time. This ensures + the correct frame for the current time is always displayed. -Ideally a/v sync would take into account the actual audio clock of the -audio hardware for the sync rather than using the system clock. -Unfortunately getting valid time data out of the audio hardware has proven -to be unreliable across platforms (and even distributions in Linux) depending -on audio hardware, audio backend etc. The current approach works fine in practice -and is a compromise until this issue can be sorted. The plan is to eventually -move to synchronising using the audio hardware. + 2) The decode thread will stop decoding interframes and read to the + next keyframe if it determines that decoding the remaining + interframes will cause playback issues. It detects this by: + a) If the amount of audio data in the audio queue drops + below a threshold whereby audio may start to skip. + b) If the video queue drops below a threshold where it + will be decoding video data that won't be displayed due + to the decode thread dropping the frame immediately. -To prevent audio skipping and framerate dropping it is very important to -make sure no blocking occurs during the decoding process and minimise -expensive time operations at the time a frame is to be displayed. This is -managed by immediately converting video data to RGB on decode (an expensive -operation to do at frame display time) and checking if the sound device will -not block before writing sound data to it. +YCbCr conversion is done on the decode thread when it is time to display +the video frame. This means frames that are skipped will not have the +YCbCr conversion done, improving playback. -Shutdown needs to ensure that the event posted to the decode -thread is completed. The decode thread can potentially block internally -inside liboggplay when reading, seeking, or its internal buffers containing -decoded data are full. When blocked in this manner a call from the main thread -to Shutdown() will hang. +The decode thread pushes decoded audio and videos frames into two +separate queues - one for audio and one for video. These are kept +separate to make it easy to constantly feed audio data to the sound +hardware while allowing frame skipping of video data. These queues are +threadsafe, and neither the decode, audio, or state machine thread should +be able to monopolize them, and cause starvation of the other threads. -This is fixed with a protocol to ensure that the decode event cleanly -completes. The nsMediaStream that the nsChannelReader uses has a -Cancel() method. Calling this before Shutdown() will close any -internal streams or listeners resulting in blocked i/o completing with -an error, and all future i/o on the stream having an error. +Both queues are bounded by a maximum size. When this size is reached +the decode thread will no longer decode video or audio depending on the +queue that has reached the threshold. -This causes the decode thread to exit and Shutdown() can occur. +During playback the audio thread will be idle (via a Wait() on the +monitor) if the audio queue is empty. Otherwise it constantly pops an +item off the queue and plays it with a blocking write to the audio +hardware (via nsAudioStream and libsydneyaudio). -If the decode thread is seeking then the same Cancel() operation -causes an error to be returned from the seek call to liboggplay which -exits out of the seek operation, and stops the seek state running on the -decode thread. - -If the decode thread is blocked due to internal decode buffers being -full, it is unblocked during the shutdown process by calling -oggplay_prepare_for_close. - -In practice the OggPlay internal buffer should never fill as we retrieve and -process the frame immediately on decoding. +The decode thread idles if the video queue is empty or if it is +not yet time to display the next frame. The Shutdown method on nsOggDecoder can spin the event loop as it waits for threads to complete. Spinning the event loop is a bad thing to happen during certain times like destruction of the media element. To work around -this the Shutdown method does nothing by queue an event to the main thread +this the Shutdown method does nothing but queue an event to the main thread to perform the actual Shutdown. This way the shutdown can occur at a safe time. @@ -263,25 +262,27 @@ when destroying the nsOggDecoder object. #include "nsCOMPtr.h" #include "nsIThread.h" #include "nsIChannel.h" -#include "nsChannelReader.h" #include "nsIObserver.h" #include "nsIFrame.h" #include "nsAutoPtr.h" #include "nsSize.h" #include "prlog.h" -#include "prmon.h" #include "gfxContext.h" #include "gfxRect.h" -#include "oggplay/oggplay.h" +#include "nsMediaStream.h" +#include "nsMediaDecoder.h" +#include "mozilla/Monitor.h" + +using mozilla::Monitor; class nsAudioStream; -class nsOggDecodeStateMachine; -class nsOggStepDecodeEvent; +class nsOggPlayStateMachine; +class nsOggReader; class nsOggDecoder : public nsMediaDecoder { - friend class nsOggDecodeStateMachine; - friend class nsOggStepDecodeEvent; + friend class nsOggReader; + friend class nsOggPlayStateMachine; // ISupports NS_DECL_ISUPPORTS @@ -336,7 +337,8 @@ class nsOggDecoder : public nsMediaDecoder virtual void NotifySuspendedStatusChanged(); virtual void NotifyBytesDownloaded(); virtual void NotifyDownloadEnded(nsresult aStatus); - // Called by nsChannelReader on the decoder thread + // Called by the decode thread to keep track of the number of bytes read + // from the resource. void NotifyBytesConsumed(PRInt64 aBytes); // Called when the video file has completed downloading. @@ -366,9 +368,6 @@ class nsOggDecoder : public nsMediaDecoder // Return PR_TRUE if seeking is supported. virtual PRBool GetSeekable(); - // Returns the channel reader. - nsChannelReader* GetReader() { return mReader; } - virtual Statistics GetStatistics(); // Suspend any media downloads that are in progress. Called by the @@ -384,23 +383,25 @@ class nsOggDecoder : public nsMediaDecoder // Tells our nsMediaStream to put all loads in the background. virtual void MoveLoadsToBackground(); - // Stop the state machine thread and drop references to the thread, - // state machine and channel reader. + // Stop the state machine thread and drop references to the thread and + // state machine. void Stop(); + // Called by the state machine to notify the decoder that the duration + // has changed. + void DurationChanged(); + protected: // Returns the monitor for other threads to synchronise access to // state. - PRMonitor* GetMonitor() - { + Monitor& GetMonitor() { return mMonitor; } // Return the current state. Can be called on any thread. If called from // a non-main thread, the decoder monitor must be held. - PlayState GetState() - { + PlayState GetState() { return mPlayState; } @@ -496,8 +497,8 @@ private: // time of the last decoded video frame). nsChannelStatistics mPlaybackStatistics; - // Thread to handle decoding of Ogg data. - nsCOMPtr mDecodeThread; + // Thread to manage playback state machine. + nsCOMPtr mStateMachineThread; // The current playback position of the media resource in units of // seconds. This is updated approximately at the framerate of the @@ -506,14 +507,12 @@ private: float mCurrentTime; // Volume that playback should start at. 0.0 = muted. 1.0 = full - // volume. Readable/Writeable from the main thread. Read from the - // audio thread when it is first started to get the initial volume - // level. + // volume. Readable/Writeable from the main thread. float mInitialVolume; // Position to seek to when the seek notification is received by the - // decoding thread. Written by the main thread and read via the - // decoding thread. Synchronised using mPlayStateMonitor. If the + // decode thread. Written by the main thread and read via the + // decode thread. Synchronised using mMonitor. If the // value is negative then no seek has been requested. When a seek is // started this is reset to negative. float mRequestedSeekTime; @@ -531,26 +530,20 @@ private: * The following member variables can be accessed from any thread. ******/ - // The state machine object for handling the decoding via - // oggplay. It is safe to call methods of this object from other - // threads. Its internal data is synchronised on a monitor. The - // lifetime of this object is after mPlayState is LOADING and before - // mPlayState is SHUTDOWN. It is safe to access it during this - // period. - nsCOMPtr mDecodeStateMachine; + // The state machine object for handling the decoding. It is safe to + // call methods of this object from other threads. Its internal data + // is synchronised on a monitor. The lifetime of this object is + // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It + // is safe to access it during this period. + nsCOMPtr mDecodeStateMachine; - // OggPlay object used to read data from a channel. Created on main - // thread. Passed to liboggplay and the locking for multithreaded - // access is handled by that library. Some methods are called from - // the decoder thread, and the state machine for that thread keeps - // a pointer to this reader. This is safe as the only methods called - // are threadsafe (via the threadsafe nsMediaStream). - nsAutoPtr mReader; + // Stream of media data. + nsAutoPtr mStream; // Monitor for detecting when the video play state changes. A call // to Wait on this monitor will block the thread until the next // state change. - PRMonitor* mMonitor; + Monitor mMonitor; // Set to one of the valid play states. It is protected by the // monitor mMonitor. This monitor must be acquired when reading or diff --git a/content/media/ogg/nsOggHacks.h b/content/media/ogg/nsOggHacks.h new file mode 100644 index 000000000000..a56d897a107c --- /dev/null +++ b/content/media/ogg/nsOggHacks.h @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +#ifndef nsOggHacks_h +#define nsOggHacks_h + +// This file contains stuff we'd rather put elsewhere, but which is +// dependent on other changes which we don't want to wait for. We plan to +// remove this file in the near future. + + +// This belongs in prtypes.h +/************************************************************************ + * MACROS: PR_INT64_MAX + * PR_INT64_MIN + * PR_UINT64_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt64 or PRUint64. +************************************************************************/ + +#define PR_INT64_MAX (~((PRInt64)(1) << 63)) +#define PR_INT64_MIN (-PR_INT64_MAX - 1) +#define PR_UINT64_MAX (~(PRUint64)(0)) + + +// This belongs in xpcom/monitor/Monitor.h, once we've made +// mozilla::Monitor non-reentrant. +namespace mozilla { + +/** + * MonitorAutoExit + * Exit the Monitor when it enters scope, and enters it when it leaves + * scope. + * + * MUCH PREFERRED to bare calls to Monitor.Exit and Enter. + */ +class NS_COM_GLUE NS_STACK_CLASS MonitorAutoExit +{ +public: + /** + * Constructor + * The constructor releases the given lock. The destructor + * acquires the lock. The lock must be held before constructing + * this object! + * + * @param aMonitor A valid mozilla::Monitor* returned by + * mozilla::Monitor::NewMonitor. It must be + * already locked. + **/ + MonitorAutoExit(mozilla::Monitor &aMonitor) : + mMonitor(&aMonitor) + { + NS_ASSERTION(mMonitor, "null monitor"); + mMonitor->AssertCurrentThreadIn(); + mMonitor->Exit(); + } + + ~MonitorAutoExit(void) + { + mMonitor->Enter(); + } + +private: + MonitorAutoExit(); + MonitorAutoExit(const MonitorAutoExit&); + MonitorAutoExit& operator =(const MonitorAutoExit&); + static void* operator new(size_t) CPP_THROW_NEW; + static void operator delete(void*); + + mozilla::Monitor* mMonitor; +}; + +} // namespace mozilla +#endif diff --git a/content/media/ogg/nsOggPlayStateMachine.cpp b/content/media/ogg/nsOggPlayStateMachine.cpp new file mode 100644 index 000000000000..558a74d5328b --- /dev/null +++ b/content/media/ogg/nsOggPlayStateMachine.cpp @@ -0,0 +1,1392 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +#include +#include "nsAudioStream.h" +#include "nsTArray.h" +#include "nsOggDecoder.h" +#include "nsOggReader.h" +#include "nsOggPlayStateMachine.h" +#include "oggplay/oggplay.h" +#include "mozilla/mozalloc.h" +#include "nsOggHacks.h" + +using namespace mozilla::layers; +using mozilla::MonitorAutoExit; + +// Adds two 32bit unsigned numbers, retuns PR_TRUE if addition succeeded, +// or PR_FALSE the if addition would result in an overflow. +static PRBool AddOverflow(PRUint32 a, PRUint32 b, PRUint32& aResult); + +#ifdef PR_LOGGING +extern PRLogModuleInfo* gOggDecoderLog; +#define LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) +#else +#define LOG(type, msg) +#endif + +// Wait this number of seconds when buffering, then leave and play +// as best as we can if the required amount of data hasn't been +// retrieved. +#define BUFFERING_WAIT 30 + +// The amount of data to retrieve during buffering is computed based +// on the download rate. BUFFERING_MIN_RATE is the minimum download +// rate to be used in that calculation to help avoid constant buffering +// attempts at a time when the average download rate has not stabilised. +#define BUFFERING_MIN_RATE 50000 +#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x)) + +// The frame rate to use if there is no video data in the resource to +// be played. +#define AUDIO_FRAME_RATE 25.0 + +nsOggPlayStateMachine::nsOggPlayStateMachine(nsOggDecoder* aDecoder) : + mDecoder(aDecoder), + mState(DECODER_STATE_DECODING_METADATA), + mAudioMonitor("media.audiostream"), + mCbCrSize(0), + mPlayDuration(0), + mBufferingEndOffset(0), + mStartTime(-1), + mEndTime(-1), + mSeekTime(0), + mCurrentFrameTime(0), + mAudioStartTime(-1), + mAudioEndTime(-1), + mVideoFrameTime(-1), + mVolume(1.0), + mSeekable(PR_TRUE), + mPositionChangeQueued(PR_FALSE), + mAudioCompleted(PR_FALSE), + mBufferExhausted(PR_FALSE), + mGotDurationFromHeader(PR_FALSE), + mStopDecodeThreads(PR_TRUE) +{ + MOZ_COUNT_CTOR(nsOggPlayStateMachine); +} + +nsOggPlayStateMachine::~nsOggPlayStateMachine() +{ + MOZ_COUNT_DTOR(nsOggPlayStateMachine); +} + +void nsOggPlayStateMachine::DecodeLoop() +{ + NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); + PRBool videoPlaying = PR_FALSE; + PRBool audioPlaying = PR_FALSE; + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + videoPlaying = HasVideo(); + audioPlaying = HasAudio(); + } + + // We want to "pump" the decode until we've got a few frames/samples decoded + // before we consider whether decode is falling behind. + PRBool audioPump = PR_TRUE; + PRBool videoPump = PR_TRUE; + + // If the video decode is falling behind the audio, we'll start dropping the + // inter-frames up until the next keyframe which is at or before the current + // playback position. skipToNextKeyframe is PR_TRUE if we're currently + // skipping up to the next keyframe. + PRBool skipToNextKeyframe = PR_FALSE; + + // If we have fewer than videoKeyframeSkipThreshold decoded frames, and + // we're not "pumping video", we'll skip the video up to the next keyframe + // which is at or after the current playback position. + const unsigned videoKeyframeSkipThreshold = 1; + + // Once we've decoded more than videoPumpThreshold video frames, we'll + // no longer be considered to be "pumping video". + const unsigned videoPumpThreshold = 5; + + // If we've got more than videoWaitThreshold decoded video frames waiting in + // the video queue, we will not decode any more video frames until they've + // been consumed by the play state machine thread. + const unsigned videoWaitThreshold = 10; + + // After the audio decode fills with more than audioPumpThresholdMs ms + // of decoded audio, we'll start to check whether the audio or video decode + // is falling behind. + const unsigned audioPumpThresholdMs = 250; + + // If audio queue has less than this many ms of decoded audio, we won't risk + // trying to decode the video, we'll skip decoding video up to the next + // keyframe. + const unsigned lowAudioThresholdMs = 100; + + // If more than this many ms of decoded audio is queued, we'll hold off + // decoding more audio. + const unsigned audioWaitThresholdMs = 2000; + + // Main decode loop. + while (videoPlaying || audioPlaying) { + PRBool audioWait = !audioPlaying; + PRBool videoWait = !videoPlaying; + { + // Wait for more data to download if we've exhausted all our + // buffered data. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + while (!mStopDecodeThreads && + mBufferExhausted && + mState != DECODER_STATE_SHUTDOWN) + { + mon.Wait(); + } + if (mState == DECODER_STATE_SHUTDOWN || mStopDecodeThreads) + break; + } + + PRUint32 videoQueueSize = mReader->mVideoQueue.GetSize(); + // Don't decode any more frames if we've filled our buffers. + // Limits memory consumption. + if (videoQueueSize > videoWaitThreshold) { + videoWait = PR_TRUE; + } + + // We don't want to consider skipping to the next keyframe if we've + // only just started up the decode loop, so wait until we've decoded + // some frames before allowing the keyframe skip. + if (videoPump && videoQueueSize >= videoPumpThreshold) { + videoPump = PR_FALSE; + } + if (!videoPump && + videoPlaying && + videoQueueSize < videoKeyframeSkipThreshold) + { + skipToNextKeyframe = PR_TRUE; + } + + PRInt64 initialDownloadPosition = 0; + PRInt64 currentTime = 0; + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + initialDownloadPosition = + mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition); + currentTime = mCurrentFrameTime + mStartTime; + } + + // Determine how much audio data is decoded ahead of the current playback + // position. + int audioQueueSize = mReader->mAudioQueue.GetSize(); + PRInt64 audioDecoded = mReader->mAudioQueue.Duration(); + + // Don't decode any audio if the audio decode is way ahead, or if we're + // skipping to the next video keyframe and the audio is marginally ahead. + if (audioDecoded > audioWaitThresholdMs || + (skipToNextKeyframe && audioDecoded > audioPumpThresholdMs)) { + audioWait = PR_TRUE; + } + if (audioPump && audioDecoded > audioPumpThresholdMs) { + audioPump = PR_FALSE; + } + if (!audioPump && audioPlaying && audioDecoded < lowAudioThresholdMs) { + skipToNextKeyframe = PR_TRUE; + } + + if (videoPlaying && !videoWait) { + videoPlaying = mReader->DecodeVideoPage(skipToNextKeyframe, currentTime); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (mDecoder->mDecoderPosition >= initialDownloadPosition) { + mBufferExhausted = PR_TRUE; + } + } + } + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + initialDownloadPosition = + mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition); + mDecoder->GetMonitor().NotifyAll(); + } + + if (audioPlaying && !audioWait) { + audioPlaying = mReader->DecodeAudioPage(); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (mDecoder->mDecoderPosition >= initialDownloadPosition) { + mBufferExhausted = PR_TRUE; + } + } + } + + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + + if (!IsPlaying() && + (!audioWait || !videoWait) && + (videoQueueSize < 2 || audioQueueSize < 2)) + { + // Transitioning from 0 to 1 frames or from 1 to 2 frames could + // affect HaveNextFrameData and hence what UpdateReadyStateForData does. + // This could change us from HAVE_CURRENT_DATA to HAVE_FUTURE_DATA + // (or even HAVE_ENOUGH_DATA), so we'd better trigger an + // update to the ready state. We only need to do this if we're + // not playing; if we're playing the playback code will post an update + // whenever it advances a frame. + UpdateReadyState(); + } + + if (mState == DECODER_STATE_SHUTDOWN || mStopDecodeThreads) { + break; + } + if ((!HasAudio() || (audioWait && audioPlaying)) && + (!HasVideo() || (videoWait && videoPlaying))) + { + // All active bitstreams' decode is well ahead of the playback + // position, we may as well wait have for the playback to catch up. + mon.Wait(); + } + } + } + + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (!mStopDecodeThreads && + mState != DECODER_STATE_SHUTDOWN && + mState != DECODER_STATE_SEEKING) + { + mState = DECODER_STATE_COMPLETED; + mDecoder->GetMonitor().NotifyAll(); + } + } + LOG(PR_LOG_DEBUG, ("Shutting down DecodeLoop this=%p", this)); +} + +PRBool nsOggPlayStateMachine::IsPlaying() +{ + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return !mPlayStartTime.IsNull(); +} + +void nsOggPlayStateMachine::AudioLoop() +{ + NS_ASSERTION(OnAudioThread(), "Should be on audio thread."); + LOG(PR_LOG_DEBUG, ("Begun audio thread/loop")); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mAudioCompleted = PR_FALSE; + } + PRInt64 audioStartTime = -1; + while (1) { + + // Wait while we're not playing, and we're not shutting down, or we're + // playing and we've got no audio to play. + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + NS_ASSERTION(mState != DECODER_STATE_DECODING_METADATA, + "Should have meta data before audio started playing."); + while (mState != DECODER_STATE_SHUTDOWN && + !mStopDecodeThreads && + (!IsPlaying() || + mState == DECODER_STATE_BUFFERING || + (mReader->mAudioQueue.GetSize() == 0 && + !mReader->mAudioQueue.AtEndOfStream()))) + { + mon.Wait(); + } + + // If we're shutting down, break out and exit the audio thread. + if (mState == DECODER_STATE_SHUTDOWN || + mStopDecodeThreads || + mReader->mAudioQueue.AtEndOfStream()) + { + break; + } + } + + NS_ASSERTION(mReader->mAudioQueue.GetSize() > 0, + "Should have data to play"); + nsAutoPtr sound(mReader->mAudioQueue.PopFront()); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + NS_ASSERTION(IsPlaying(), "Should be playing"); + // Awaken the decode loop if it's waiting for space to free up in the + // audio queue. + mDecoder->GetMonitor().NotifyAll(); + } + + if (audioStartTime == -1) { + // Remember the presentation time of the first audio sample we play. + // We add this to the position/played duration of the audio stream to + // determine the audio clock time. Used for A/V sync. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mAudioStartTime = audioStartTime = sound->mTime; + LOG(PR_LOG_DEBUG, ("First audio sample has timestamp %lldms", mAudioStartTime)); + } + + { + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + // The state machine could have paused since we've released the decoder + // monitor and acquired the audio monitor. Rather than acquire both + // monitors, the audio stream also maintains whether its paused or not. + // This prevents us from doing a blocking write while holding the audio + // monitor while paused; we would block, and the state machine won't be + // able to acquire the audio monitor in order to resume or destroy the + // audio stream. + if (!mAudioStream->IsPaused()) { + mAudioStream->Write(sound->mAudioData, + sound->AudioDataLength(), + PR_TRUE); + mAudioEndTime = sound->mTime + sound->mDuration; + } else { + mReader->mAudioQueue.PushFront(sound); + sound.forget(); + } + } + } + sound = nsnull; + + if (mReader->mAudioQueue.AtEndOfStream()) { + // Last sample pushed to audio hardware, wait for the audio to finish, + // before the audio thread terminates. + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + mAudioStream->Drain(); + } + LOG(PR_LOG_DEBUG, ("%p Reached audio stream end.", mDecoder)); + } + } + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mAudioCompleted = PR_TRUE; + } + LOG(PR_LOG_DEBUG, ("Audio stream finished playing, audio thread exit")); +} + +nsresult nsOggPlayStateMachine::Init() +{ + mReader = new nsOggReader(this); + return mReader->Init(); +} + +void nsOggPlayStateMachine::StopPlayback(eStopMode aMode) +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + // Reset mPlayStartTime before we pause/shutdown the nsAudioStream. This is + // so that if the audio loop is about to write audio, it will have the chance + // to check to see if we're paused and not write the audio. If not, the + // audio thread can block in the write, and we deadlock trying to acquire + // the audio monitor upon resume playback. + if (IsPlaying()) { + mPlayDuration += TimeStamp::Now() - mPlayStartTime; + mPlayStartTime = TimeStamp(); + } + if (HasAudio()) { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + if (aMode == AUDIO_PAUSE) { + mAudioStream->Pause(); + } else if (aMode == AUDIO_SHUTDOWN) { + mAudioStream->Shutdown(); + mAudioStream = nsnull; + } + } + } +} + +void nsOggPlayStateMachine::StartPlayback() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + NS_ASSERTION(!IsPlaying(), "Shouldn't be playing when StartPlayback() is called"); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + LOG(PR_LOG_DEBUG, ("%p StartPlayback", mDecoder)); + if (HasAudio()) { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + // We have an audiostream, so it must have been paused the last time + // StopPlayback() was called. + mAudioStream->Resume(); + } else { + // No audiostream, create one. + mAudioStream = new nsAudioStream(); + mAudioStream->Init(mInfo.mAudioChannels, + mInfo.mAudioRate, + nsAudioStream::FORMAT_FLOAT32); + mAudioStream->SetVolume(mVolume); + } + } + mPlayStartTime = TimeStamp::Now(); + mDecoder->GetMonitor().NotifyAll(); +} + +void nsOggPlayStateMachine::UpdatePlaybackPosition(PRInt64 aTime) +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + NS_ASSERTION(mStartTime >= 0, "Should have positive mStartTime"); + mCurrentFrameTime = aTime - mStartTime; + NS_ASSERTION(mCurrentFrameTime >= 0, "CurrentTime should be positive!"); + if (aTime > mEndTime) { + NS_ASSERTION(mCurrentFrameTime > GetDuration(), + "CurrentTime must be after duration if aTime > endTime!"); + mEndTime = aTime; + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, DurationChanged); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + } + if (!mPositionChangeQueued) { + mPositionChangeQueued = PR_TRUE; + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackPositionChanged); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + } +} + +void nsOggPlayStateMachine::ClearPositionChangeFlag() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + mPositionChangeQueued = PR_FALSE; +} + +nsHTMLMediaElement::NextFrameStatus nsOggPlayStateMachine::GetNextFrameStatus() +{ + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (IsBuffering() || IsSeeking()) { + return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING; + } else if (HaveNextFrameData()) { + return nsHTMLMediaElement::NEXT_FRAME_AVAILABLE; + } + return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE; +} + +void nsOggPlayStateMachine::SetVolume(float volume) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + { + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + mAudioStream->SetVolume(volume); + } + } + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mVolume = volume; + } +} + +float nsOggPlayStateMachine::GetCurrentTime() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return (float)mCurrentFrameTime / 1000.0; +} + +PRInt64 nsOggPlayStateMachine::GetDuration() +{ + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + if (mEndTime == -1 || mStartTime == -1) + return -1; + return mEndTime - mStartTime; +} + +void nsOggPlayStateMachine::SetDuration(PRInt64 aDuration) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + if (mStartTime != -1) { + mEndTime = mStartTime + aDuration; + } else { + mStartTime = 0; + mEndTime = aDuration; + } +} + +void nsOggPlayStateMachine::SetSeekable(PRBool aSeekable) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + mSeekable = aSeekable; +} + +void nsOggPlayStateMachine::Shutdown() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + + // Once we've entered the shutdown state here there's no going back. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + + // Change state before issuing shutdown request to threads so those + // threads can start exiting cleanly during the Shutdown call. + LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN", mDecoder)); + mState = DECODER_STATE_SHUTDOWN; + mDecoder->GetMonitor().NotifyAll(); +} + +void nsOggPlayStateMachine::Decode() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + // When asked to decode, switch to decoding only if + // we are currently buffering. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (mState == DECODER_STATE_BUFFERING) { + LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); + mState = DECODER_STATE_DECODING; + mDecoder->GetMonitor().NotifyAll(); + } +} + +void nsOggPlayStateMachine::ResetPlayback() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mVideoFrameTime = -1; + mAudioStartTime = -1; + mAudioEndTime = -1; + mAudioCompleted = PR_FALSE; +} + +void nsOggPlayStateMachine::Seek(float aTime) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mDecoder->GetMonitor()); + // nsOggDecoder::mPlayState should be SEEKING while we seek, and + // in that case nsOggDecoder shouldn't be calling us. + NS_ASSERTION(mState != DECODER_STATE_SEEKING, + "We shouldn't already be seeking"); + NS_ASSERTION(mState >= DECODER_STATE_DECODING, + "We should have loaded metadata"); + double t = aTime * 1000.0; + if (t > PR_INT64_MAX) { + // Prevent integer overflow. + return; + } + + mSeekTime = static_cast(t) + mStartTime; + NS_ASSERTION(mSeekTime >= mStartTime && mSeekTime <= mEndTime, + "Can only seek in range [0,duration]"); + + // Bound the seek time to be inside the media range. + NS_ASSERTION(mStartTime != -1, "Should know start time by now"); + NS_ASSERTION(mEndTime != -1, "Should know end time by now"); + mSeekTime = NS_MIN(mSeekTime, mEndTime); + mSeekTime = NS_MAX(mStartTime, mSeekTime); + LOG(PR_LOG_DEBUG, ("%p Changed state to SEEKING (to %f)", mDecoder, aTime)); + mState = DECODER_STATE_SEEKING; +} + +void nsOggPlayStateMachine::StopDecodeThreads() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + mStopDecodeThreads = PR_TRUE; + mDecoder->GetMonitor().NotifyAll(); + if (mDecodeThread) { + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + mDecodeThread->Shutdown(); + } + mDecodeThread = nsnull; + } + if (mAudioThread) { + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + mAudioThread->Shutdown(); + } + mAudioThread = nsnull; + } +} + +nsresult +nsOggPlayStateMachine::StartDecodeThreads() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + mStopDecodeThreads = PR_FALSE; + if (!mDecodeThread && mState < DECODER_STATE_COMPLETED) { + nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread)); + if (NS_FAILED(rv)) { + mState = DECODER_STATE_SHUTDOWN; + return rv; + } + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggPlayStateMachine, this, DecodeLoop); + mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL); + } + if (HasAudio() && !mAudioThread) { + nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread)); + if (NS_FAILED(rv)) { + mState = DECODER_STATE_SHUTDOWN; + return rv; + } + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggPlayStateMachine, this, AudioLoop); + mAudioThread->Dispatch(event, NS_DISPATCH_NORMAL); + } + return NS_OK; +} + +nsresult nsOggPlayStateMachine::Run() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + nsMediaStream* stream = mDecoder->mStream; + NS_ENSURE_TRUE(stream, NS_ERROR_NULL_POINTER); + + while (PR_TRUE) { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + switch (mState) { + case DECODER_STATE_SHUTDOWN: + if (IsPlaying()) { + StopPlayback(AUDIO_SHUTDOWN); + } + StopDecodeThreads(); + NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN, + "How did we escape from the shutdown state???"); + return NS_OK; + + case DECODER_STATE_DECODING_METADATA: + { + LoadOggHeaders(); + if (mState == DECODER_STATE_SHUTDOWN) { + continue; + } + + VideoData* videoData = FindStartTime(); + if (videoData) { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + RenderVideoFrame(videoData); + } + + // Start the decode threads, so that we can pre buffer the streams. + // and calculate the start time in order to determine the duration. + if (NS_FAILED(StartDecodeThreads())) { + continue; + } + + NS_ASSERTION(mStartTime != -1, "Must have start time"); + NS_ASSERTION((!HasVideo() && !HasAudio()) || + !mSeekable || mEndTime != -1, + "Active seekable media should have end time"); + NS_ASSERTION(!mSeekable || GetDuration() != -1, "Seekable media should have duration"); + LOG(PR_LOG_DEBUG, ("%p Media goes from %lldms to %lldms (duration %lldms) seekable=%d", + mDecoder, mStartTime, mEndTime, GetDuration(), mSeekable)); + + if (mState == DECODER_STATE_SHUTDOWN) + continue; + + // Inform the element that we've loaded the Ogg metadata and the + // first frame. + nsCOMPtr metadataLoadedEvent = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, MetadataLoaded); + NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); + + if (mState == DECODER_STATE_DECODING_METADATA) { + LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder)); + mState = DECODER_STATE_DECODING; + } + + // Start playback. + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + if (!IsPlaying()) { + StartPlayback(); + } + } + } + break; + + case DECODER_STATE_DECODING: + { + if (NS_FAILED(StartDecodeThreads())) { + continue; + } + + AdvanceFrame(); + + if (mState != DECODER_STATE_DECODING) + continue; + + if (mBufferExhausted && + mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING && + !mDecoder->mStream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && + !mDecoder->mStream->IsSuspendedByCache()) { + // There is at most one frame in the queue and there's + // more data to load. Let's buffer to make sure we can play a + // decent amount of video in the future. + if (IsPlaying()) { + StopPlayback(AUDIO_PAUSE); + mDecoder->GetMonitor().NotifyAll(); + } + + // We need to tell the element that buffering has started. + // We can't just directly send an asynchronous runnable that + // eventually fires the "waiting" event. The problem is that + // there might be pending main-thread events, such as "data + // received" notifications, that mean we're not actually still + // buffering by the time this runnable executes. So instead + // we just trigger UpdateReadyStateForData; when it runs, it + // will check the current state and decide whether to tell + // the element we're buffering or not. + UpdateReadyState(); + + mBufferingStart = TimeStamp::Now(); + PRPackedBool reliable; + double playbackRate = mDecoder->ComputePlaybackRate(&reliable); + mBufferingEndOffset = mDecoder->mDecoderPosition + + BUFFERING_RATE(playbackRate) * BUFFERING_WAIT; + mState = DECODER_STATE_BUFFERING; + LOG(PR_LOG_DEBUG, ("Changed state from DECODING to BUFFERING")); + } else { + if (mBufferExhausted) { + // This will wake up the decode thread and force it to try to + // decode video and audio. This guarantees we make progress. + mBufferExhausted = PR_FALSE; + mDecoder->GetMonitor().NotifyAll(); + } + } + + } + break; + + case DECODER_STATE_SEEKING: + { + // During the seek, don't have a lock on the decoder state, + // otherwise long seek operations can block the main thread. + // The events dispatched to the main thread are SYNC calls. + // These calls are made outside of the decode monitor lock so + // it is safe for the main thread to makes calls that acquire + // the lock since it won't deadlock. We check the state when + // acquiring the lock again in case shutdown has occurred + // during the time when we didn't have the lock. + PRInt64 seekTime = mSeekTime; + mDecoder->StopProgressUpdates(); + + StopPlayback(AUDIO_SHUTDOWN); + StopDecodeThreads(); + ResetPlayback(); + + // SeekingStarted will do a UpdateReadyStateForData which will + // inform the element and its users that we have no frames + // to display + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + nsCOMPtr startEvent = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStarted); + NS_DispatchToMainThread(startEvent, NS_DISPATCH_SYNC); + } + if (mCurrentFrameTime != mSeekTime - mStartTime) { + nsresult res; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + // Now perform the seek. We must not hold the state machine monitor + // while we seek, since the seek decodes. + res = mReader->Seek(seekTime, mStartTime, mEndTime); + } + if (NS_SUCCEEDED(res)){ + SoundData* audio = HasAudio() ? mReader->mAudioQueue.PeekFront() : nsnull; + if (audio) { + mPlayDuration = TimeDuration::FromMilliseconds(audio->mTime); + } + if (HasVideo()) { + nsAutoPtr video(mReader->mVideoQueue.PeekFront()); + if (video) { + RenderVideoFrame(video); + if (!audio) { + NS_ASSERTION(video->mTime <= seekTime && + seekTime <= video->mTime + mInfo.mCallbackPeriod, + "Seek target should lie inside the first frame after seek"); + mPlayDuration = TimeDuration::FromMilliseconds(seekTime); + } + } + mReader->mVideoQueue.PopFront(); + } + UpdatePlaybackPosition(seekTime); + } + } + mDecoder->StartProgressUpdates(); + if (mState == DECODER_STATE_SHUTDOWN) + continue; + + // Try to decode another frame to detect if we're at the end... + LOG(PR_LOG_DEBUG, ("Seek completed, mCurrentFrameTime=%lld\n", mCurrentFrameTime)); + + // Change state to DECODING or COMPLETED now. SeekingStopped will + // call nsOggPlayStateMachine::Seek to reset our state to SEEKING + // if we need to seek again. + + nsCOMPtr stopEvent; + if (mCurrentFrameTime == mEndTime) { + LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lldms) to COMPLETED", + mDecoder, seekTime)); + stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd); + mState = DECODER_STATE_COMPLETED; + } else { + LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lldms) to DECODING", + mDecoder, seekTime)); + stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped); + mState = DECODER_STATE_DECODING; + } + mBufferExhausted = PR_FALSE; + mDecoder->GetMonitor().NotifyAll(); + + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC); + } + } + break; + + case DECODER_STATE_BUFFERING: + { + TimeStamp now = TimeStamp::Now(); + if (now - mBufferingStart < TimeDuration::FromSeconds(BUFFERING_WAIT) && + mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition) < mBufferingEndOffset && + !mDecoder->mStream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && + !mDecoder->mStream->IsSuspendedByCache()) { + LOG(PR_LOG_DEBUG, + ("In buffering: buffering data until %d bytes available or %f seconds", + PRUint32(mBufferingEndOffset - mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition)), + BUFFERING_WAIT - (now - mBufferingStart).ToSeconds())); + Wait(1000); + if (mState == DECODER_STATE_SHUTDOWN) + continue; + } else { + LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); + LOG(PR_LOG_DEBUG, ("%p Buffered for %lf seconds", + mDecoder, + (TimeStamp::Now() - mBufferingStart).ToSeconds())); + mState = DECODER_STATE_DECODING; + } + + if (mState != DECODER_STATE_BUFFERING) { + mBufferExhausted = PR_FALSE; + // Notify to allow blocked decoder thread to continue + mDecoder->GetMonitor().NotifyAll(); + UpdateReadyState(); + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + if (!IsPlaying()) { + StartPlayback(); + } + } + } + + break; + } + + case DECODER_STATE_COMPLETED: + { + if (NS_FAILED(StartDecodeThreads())) { + continue; + } + + // Play the remaining media. + while (mState == DECODER_STATE_COMPLETED && + (mReader->mVideoQueue.GetSize() > 0 || + (HasAudio() && !mAudioCompleted))) + { + AdvanceFrame(); + } + + if (mAudioStream) { + // Close the audop stream so that next time audio is used a new stream + // is created. The StopPlayback call also resets the IsPlaying() state + // so audio is restarted correctly. + StopPlayback(AUDIO_SHUTDOWN); + } + + if (mState != DECODER_STATE_COMPLETED) + continue; + + LOG(PR_LOG_DEBUG, ("Shutting down the state machine thread")); + StopDecodeThreads(); + + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + PRInt64 videoTime = HasVideo() ? (mVideoFrameTime + mInfo.mCallbackPeriod) : 0; + PRInt64 clockTime = NS_MAX(mEndTime, NS_MAX(videoTime, GetAudioClock())); + UpdatePlaybackPosition(clockTime); + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded); + NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); + } + } + + while (mState == DECODER_STATE_COMPLETED) { + mDecoder->GetMonitor().Wait(); + } + } + break; + } + } + + return NS_OK; +} + +static void ToARGBHook(const PlanarYCbCrImage::Data& aData, PRUint8* aOutput) +{ + OggPlayYUVChannels yuv; + NS_ASSERTION(aData.mYStride == aData.mYSize.width, + "Stride not supported"); + NS_ASSERTION(aData.mCbCrStride == aData.mCbCrSize.width, + "Stride not supported"); + yuv.ptry = aData.mYChannel; + yuv.ptru = aData.mCbChannel; + yuv.ptrv = aData.mCrChannel; + yuv.uv_width = aData.mCbCrSize.width; + yuv.uv_height = aData.mCbCrSize.height; + yuv.y_width = aData.mYSize.width; + yuv.y_height = aData.mYSize.height; + + OggPlayRGBChannels rgb; + rgb.ptro = aOutput; + rgb.rgb_width = aData.mYSize.width; + rgb.rgb_height = aData.mYSize.height; + + oggplay_yuv2bgra(&yuv, &rgb); +} + +void nsOggPlayStateMachine::RenderVideoFrame(VideoData* aData) +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + + if (aData->mDuplicate) { + return; + } + + unsigned xSubsample = (aData->mBuffer[1].width != 0) ? + (aData->mBuffer[0].width / aData->mBuffer[1].width) : 0; + + unsigned ySubsample = (aData->mBuffer[1].height != 0) ? + (aData->mBuffer[0].height / aData->mBuffer[1].height) : 0; + + if (xSubsample == 0 || ySubsample == 0) { + // We can't perform yCbCr to RGB, so we can't render the frame... + return; + } + NS_ASSERTION(mInfo.mPicture.width != 0 && mInfo.mPicture.height != 0, + "We can only render non-zero-sized video"); + + unsigned cbCrStride = mInfo.mPicture.width / xSubsample; + unsigned cbCrHeight = mInfo.mPicture.height / ySubsample; + + // Ensure the picture size specified in the headers can be extracted out of + // the frame we've been supplied without indexing out of bounds. + PRUint32 picXLimit; + PRUint32 picYLimit; + if (!AddOverflow(mInfo.mPicture.x, mInfo.mPicture.width, picXLimit) || + picXLimit > PR_ABS(aData->mBuffer[0].stride) || + !AddOverflow(mInfo.mPicture.y, mInfo.mPicture.height, picYLimit) || + picYLimit > PR_ABS(aData->mBuffer[0].height)) + { + // The specified picture dimensions can't be contained inside the video + // frame, we'll stomp memory if we try to copy it. Fail. + return; + } + + unsigned cbCrSize = PR_ABS(aData->mBuffer[0].stride * aData->mBuffer[0].height) + + PR_ABS(aData->mBuffer[1].stride * aData->mBuffer[1].height) * 2; + if (cbCrSize != mCbCrSize) { + mCbCrSize = cbCrSize; + mCbCrBuffer = static_cast(moz_xmalloc(cbCrSize)); + if (!mCbCrBuffer) { + // Malloc failed... + NS_WARNING("Malloc failure allocating YCbCr->RGB buffer"); + return; + } + } + + unsigned char* data = mCbCrBuffer.get(); + + unsigned char* y = data; + unsigned char* cb = y + (mInfo.mPicture.width * PR_ABS(aData->mBuffer[0].height)); + unsigned char* cr = cb + (cbCrStride * PR_ABS(aData->mBuffer[1].height)); + + unsigned char* p = y; + unsigned yStride = mInfo.mPicture.width; + unsigned char* q = aData->mBuffer[0].data + mInfo.mPicture.x + + aData->mBuffer[0].stride * mInfo.mPicture.y; + for(unsigned i=0; i < mInfo.mPicture.height; ++i) { + NS_ASSERTION(q + mInfo.mPicture.width < + aData->mBuffer[0].data + aData->mBuffer[0].stride * aData->mBuffer[0].height, + "Y read must be in bounds"); + NS_ASSERTION(p + mInfo.mPicture.width < data + mCbCrSize, + "Memory copy 1 will stomp"); + memcpy(p, q, mInfo.mPicture.width); + p += mInfo.mPicture.width; + q += aData->mBuffer[0].stride; + } + + unsigned xo = xSubsample ? (mInfo.mPicture.x / xSubsample) : 0; + unsigned yo = ySubsample ? aData->mBuffer[1].stride * (mInfo.mPicture.y / ySubsample) : 0; + + unsigned cbCrOffset = xo+yo; + p = cb; + q = aData->mBuffer[1].data + cbCrOffset; + unsigned char* p2 = cr; + unsigned char* q2 = aData->mBuffer[2].data + cbCrOffset; +#ifdef DEBUG + unsigned char* buffer1Limit = + aData->mBuffer[1].data + aData->mBuffer[1].stride * aData->mBuffer[1].height; + unsigned char* buffer2Limit = + aData->mBuffer[2].data + aData->mBuffer[2].stride * aData->mBuffer[2].height; +#endif + for(unsigned i=0; i < cbCrHeight; ++i) { + NS_ASSERTION(q + cbCrStride <= buffer1Limit, + "Cb source read must be within bounds"); + NS_ASSERTION(q2 + cbCrStride <= buffer2Limit, + "Cr source read must be within bounds"); + NS_ASSERTION(p + cbCrStride < data + mCbCrSize, + "Cb write destination must be within bounds"); + NS_ASSERTION(p2 + cbCrStride < data + mCbCrSize, + "Cr write destination must be within bounds"); + memcpy(p, q, cbCrStride); + memcpy(p2, q2, cbCrStride); + p += cbCrStride; + p2 += cbCrStride; + q += aData->mBuffer[1].stride; + q2 += aData->mBuffer[2].stride; + } + + ImageContainer* container = mDecoder->GetImageContainer(); + // Currently our Ogg decoder only knows how to output to PLANAR_YCBCR + // format. + Image::Format format = Image::PLANAR_YCBCR; + nsRefPtr image; + if (container) { + image = container->CreateImage(&format, 1); + } + if (image) { + NS_ASSERTION(image->GetFormat() == Image::PLANAR_YCBCR, + "Wrong format?"); + PlanarYCbCrImage* videoImage = static_cast(image.get()); + // XXX this is only temporary until we get YCbCr code in the layer + // system. + videoImage->SetRGBConverter(ToARGBHook); + PlanarYCbCrImage::Data data; + data.mYChannel = y; + data.mYSize = gfxIntSize(mInfo.mPicture.width, mInfo.mPicture.height); + data.mYStride = mInfo.mPicture.width; + data.mCbChannel = cb; + data.mCrChannel = cr; + data.mCbCrSize = gfxIntSize(cbCrStride, cbCrHeight); + data.mCbCrStride = cbCrStride; + videoImage->SetData(data); + mDecoder->SetVideoData(data.mYSize, mInfo.mAspectRatio, image); + } +} + +PRInt64 +nsOggPlayStateMachine::GetAudioClock() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + if (!mAudioStream || !HasAudio()) + return -1; + PRInt64 t = mAudioStream->GetPosition(); + return (t == -1) ? -1 : t + mAudioStartTime; +} + +void nsOggPlayStateMachine::AdvanceFrame() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + // When it's time to display a frame, decode the frame and display it. + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + if (!IsPlaying()) { + StartPlayback(); + mDecoder->GetMonitor().NotifyAll(); + } + + if (HasAudio() && mAudioStartTime == -1 && !mAudioCompleted) { + // We've got audio (so we should sync off the audio clock), but we've + // not played a sample on the audio thread, so we can't get a time + // from the audio clock. Just wait and then return, to give the audio + // clock time to tick. + Wait(mInfo.mCallbackPeriod); + return; + } + + // Determine the clock time. If we've got audio, and we've not reached + // the end of the audio, use the audio clock. However if we've finished + // audio, or don't have audio, use the system clock. + PRInt64 clock_time = -1; + PRInt64 audio_time = GetAudioClock(); + if (HasAudio() && !mAudioCompleted && audio_time != -1) { + clock_time = audio_time; + // Resync against the audio clock, while we're trusting the + // audio clock. This ensures no "drift", particularly on Linux. + mPlayStartTime = TimeStamp::Now() - TimeDuration::FromMilliseconds(clock_time); + } else { + // Sound is disabled on this system. Sync to the system clock. + TimeDuration t = TimeStamp::Now() - mPlayStartTime + mPlayDuration; + clock_time = (PRInt64)(1000 * t.ToSeconds()); + // Ensure the clock can never go backwards. + NS_ASSERTION(mCurrentFrameTime <= clock_time, "Clock should go forwards"); + clock_time = NS_MAX(mCurrentFrameTime, clock_time) + mStartTime; + } + + NS_ASSERTION(clock_time >= mStartTime, "Should have positive clock time."); + nsAutoPtr videoData; + if (mReader->mVideoQueue.GetSize() > 0) { + VideoData* data = mReader->mVideoQueue.PeekFront(); + while (clock_time >= data->mTime) { + mVideoFrameTime = data->mTime; + videoData = data; + mReader->mVideoQueue.PopFront(); + if (mReader->mVideoQueue.GetSize() == 0) + break; + data = mReader->mVideoQueue.PeekFront(); + } + } + + if (videoData) { + // Decode one frame and display it + NS_ASSERTION(videoData->mTime >= mStartTime, "Should have positive frame time"); + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + // If we have video, we want to increment the clock in steps of the frame + // duration. + RenderVideoFrame(videoData); + } + mDecoder->GetMonitor().NotifyAll(); + videoData = nsnull; + } + + // Cap the current time to the larger of the audio and video end time. + // This ensures that if we're running off the system clock, we don't + // advance the clock to after the media end time. + if (mVideoFrameTime != -1 || mAudioEndTime != -1) { + // These will be non -1 if we've displayed a video frame, or played an audio sample. + clock_time = NS_MIN(clock_time, NS_MAX(mVideoFrameTime, mAudioEndTime)); + if (clock_time - mStartTime > mCurrentFrameTime) { + // Only update the playback position if the clock time is greater + // than the previous playback position. The audio clock can + // sometimes report a time less than its previously reported in + // some situations, and we need to gracefully handle that. + UpdatePlaybackPosition(clock_time); + } + } + + // If the number of audio/video samples queued has changed, either by + // this function popping and playing a video sample, or by the audio + // thread popping and playing an audio sample, we may need to update our + // ready state. Post an update to do so. + UpdateReadyState(); + + Wait(mInfo.mCallbackPeriod); + } else { + if (IsPlaying()) { + StopPlayback(AUDIO_PAUSE); + mDecoder->GetMonitor().NotifyAll(); + } + + if (mState == DECODER_STATE_DECODING || + mState == DECODER_STATE_COMPLETED) { + mDecoder->GetMonitor().Wait(); + } + } +} + +void nsOggPlayStateMachine::Wait(PRUint32 aMs) { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + TimeStamp end = TimeStamp::Now() + TimeDuration::FromMilliseconds(aMs); + TimeStamp now; + while ((now = TimeStamp::Now()) < end && + mState != DECODER_STATE_SHUTDOWN && + mState != DECODER_STATE_SEEKING) + { + TimeDuration d = end - now; + PRInt64 ms = d.ToSeconds() * 1000; + if (ms == 0) { + break; + } + NS_ASSERTION(ms <= aMs && ms > 0, + "nsOggPlayStateMachine::Wait interval very wrong!"); + mDecoder->GetMonitor().Wait(PR_MillisecondsToInterval(ms)); + } +} + +void nsOggPlayStateMachine::LoadOggHeaders() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + LOG(PR_LOG_DEBUG, ("Loading Ogg Headers")); + + nsMediaStream* stream = mDecoder->mStream; + + nsOggInfo info; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + mReader->ReadOggHeaders(info); + } + mInfo = info; + mDecoder->StartProgressUpdates(); + + if (!mInfo.mHasVideo && !mInfo.mHasAudio) { + mState = DECODER_STATE_SHUTDOWN; + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, DecodeError); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + return; + } + + if (!mInfo.mHasVideo) { + mInfo.mCallbackPeriod = 1000 / AUDIO_FRAME_RATE; + } + LOG(PR_LOG_DEBUG, ("%p Callback Period: %u", mDecoder, mInfo.mCallbackPeriod)); + + // TODO: Get the duration from Skeleton index, if available. + + // Get the duration from the Ogg file. We only do this if the + // content length of the resource is known as we need to seek + // to the end of the file to get the last time field. We also + // only do this if the resource is seekable and if we haven't + // already obtained the duration via an HTTP header. + mGotDurationFromHeader = (GetDuration() != -1); + if (mState != DECODER_STATE_SHUTDOWN && + stream->GetLength() >= 0 && + mSeekable && + mEndTime == -1) + { + mDecoder->StopProgressUpdates(); + FindEndTime(); + mDecoder->StartProgressUpdates(); + mDecoder->UpdatePlaybackRate(); + } +} + +VideoData* nsOggPlayStateMachine::FindStartTime() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + PRInt64 startTime = 0; + mStartTime = 0; + VideoData* v = nsnull; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + v = mReader->FindStartTime(mInfo.mDataOffset, startTime); + } + if (startTime != 0) { + mStartTime = startTime; + if (mGotDurationFromHeader) { + NS_ASSERTION(mEndTime != -1, + "We should have mEndTime as supplied duration here"); + // We were specified a duration from a Content-Duration HTTP header. + // Adjust mEndTime so that mEndTime-mStartTime matches the specified + // duration. + mEndTime = mStartTime + mEndTime; + } + } + LOG(PR_LOG_DEBUG, ("%p Media start time is %lldms", mDecoder, mStartTime)); + return v; +} + +void nsOggPlayStateMachine::FindEndTime() +{ + NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + nsMediaStream* stream = mDecoder->mStream; + + // Seek to the end of file to find the length and duration. + PRInt64 length = stream->GetLength(); + NS_ASSERTION(length > 0, "Must have a content length to get end time"); + + mEndTime = 0; + PRInt64 endTime = 0; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + endTime = mReader->FindEndTime(length); + } + if (endTime != -1) { + mEndTime = endTime; + } + + NS_ASSERTION(mInfo.mDataOffset > 0, + "Should have offset of first non-header page"); + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + stream->Seek(nsISeekableStream::NS_SEEK_SET, mInfo.mDataOffset); + } + LOG(PR_LOG_DEBUG, ("%p Media end time is %lldms", mDecoder, mEndTime)); +} + +void nsOggPlayStateMachine::UpdateReadyState() { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + nsCOMPtr event; + switch (GetNextFrameStatus()) { + case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING: + event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailableBuffering); + break; + case nsHTMLMediaElement::NEXT_FRAME_AVAILABLE: + event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameAvailable); + break; + case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE: + event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailable); + break; + default: + PR_NOT_REACHED("unhandled frame state"); + } + + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); +} + + +static PRBool AddOverflow(PRUint32 a, PRUint32 b, PRUint32& aResult) { + PRUint64 rl = static_cast(a) + static_cast(b); + if (rl > PR_UINT32_MAX) { + return PR_FALSE; + } + aResult = static_cast(rl); + return true; +} diff --git a/content/media/ogg/nsOggPlayStateMachine.h b/content/media/ogg/nsOggPlayStateMachine.h new file mode 100644 index 000000000000..cff645e51204 --- /dev/null +++ b/content/media/ogg/nsOggPlayStateMachine.h @@ -0,0 +1,419 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ +#if !defined(nsOggPlayStateMachine_h__) +#define nsOggPlayStateMachine_h__ + +#include "prmem.h" +#include "nsThreadUtils.h" +#include "nsOggReader.h" +#include "nsOggDecoder.h" +#include "nsHTMLMediaElement.h" +#include "mozilla/Monitor.h" + +using mozilla::TimeDuration; +using mozilla::TimeStamp; + +class nsOggDecoder; + +// Checks if we're on a specific thread or not. Used in assertions to +// verify thread safety. +static inline PRBool IsThread(nsIThread* aThread) { + return NS_GetCurrentThread() == aThread; +} + +/* + The playback state machine class. This manages the decoding in the + nsOggReader on the decode thread, seeking and in-sync-playback on the + state machine thread, and controls the audio "push" thread. + + All internal state is synchronised via the decoder monitor. NotifyAll + on the monitor is called when the state of the state machine is changed + by the main thread. The following changes to state cause a notify: + + mState and data related to that state changed (mSeekTime, etc) + Ogg Metadata Loaded + First Frame Loaded + Frame decoded + data pushed or popped from the video and audio queues + + See nsOggDecoder.h for more details. +*/ +class nsOggPlayStateMachine : public nsRunnable +{ +public: + // Enumeration for the valid states + enum State { + DECODER_STATE_DECODING_METADATA, + DECODER_STATE_DECODING, + DECODER_STATE_SEEKING, + DECODER_STATE_BUFFERING, + DECODER_STATE_COMPLETED, + DECODER_STATE_SHUTDOWN + }; + + nsOggPlayStateMachine(nsOggDecoder* aDecoder); + ~nsOggPlayStateMachine(); + + // Initializes the state machine, returns NS_OK on success, or + // NS_ERROR_FAILURE on failure. + nsresult Init(); + + // Cause state transitions. These methods obtain the decoder monitor + // to synchronise the change of state, and to notify other threads + // that the state has changed. + void Shutdown(); + void Decode(); + + // Seeks to aTime seconds. + void Seek(float aTime); + + // State machine thread run function. Polls the state, sends frames to be + // displayed at appropriate times, and generally manages the decode. + NS_IMETHOD Run(); + + // This is called on the state machine thread and audio thread. + // The decoder monitor must be obtained before calling this. + PRBool HasAudio() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + return mInfo.mHasAudio; + } + + // This is called on the state machine thread and audio thread. + // The decoder monitor must be obtained before calling this. + PRBool HasVideo() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + return mInfo.mHasVideo; + } + + // Returns the current playback position in seconds. + // Called from the main thread to get the current frame time. The decoder + // monitor must be obtained before calling this. + float GetCurrentTime(); + + // Called from the main thread to get the duration. The decoder monitor + // must be obtained before calling this. It is in units of milliseconds. + PRInt64 GetDuration(); + + // Called from the main thread to set the duration of the media resource + // if it is able to be obtained via HTTP headers. The decoder monitor + // must be obtained before calling this. + void SetDuration(PRInt64 aDuration); + + // Called from the main thread to set whether the media resource can + // be seeked. The decoder monitor must be obtained before calling this. + void SetSeekable(PRBool aSeekable); + + // Set the audio volume. The decoder monitor must be obtained before + // calling this. + void SetVolume(float aVolume); + + // Clear the flag indicating that a playback position change event + // is currently queued. This is called from the main thread and must + // be called with the decode monitor held. + void ClearPositionChangeFlag(); + + // Should be called by main thread. + PRBool HaveNextFrameData() const { + PRUint32 audioQueueSize = mReader->mAudioQueue.GetSize(); + return (mReader->mVideoQueue.GetSize() > 0 && + (!HasAudio() || audioQueueSize > 0)) || + audioQueueSize > 0; + } + + // Must be called with the decode monitor held. + PRBool IsBuffering() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return mState == nsOggPlayStateMachine::DECODER_STATE_BUFFERING; + } + + // Must be called with the decode monitor held. + PRBool IsSeeking() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return mState == nsOggPlayStateMachine::DECODER_STATE_SEEKING; + } + + // Functions used by assertions to ensure we're calling things + // on the appropriate threads. + PRBool OnStateMachineThread() { + return IsThread(mDecoder->mStateMachineThread); + } + + PRBool OnDecodeThread() { + return IsThread(mDecodeThread); + } + + PRBool OnAudioThread() { + return IsThread(mAudioThread); + } + + // Decode loop, called on the decode thread. + void DecodeLoop(); + + // The decoder object that created this state machine. The decoder + // always outlives us since it controls our lifetime. This is accessed + // read only on the AV, state machine, audio and main thread. + nsOggDecoder* mDecoder; + + // Update the playback position. This can result in a timeupdate event + // and an invalidate of the frame being dispatched asynchronously if + // there is no such event currently queued. + // Only called on the decoder thread. Must be called with + // the decode monitor held. + void UpdatePlaybackPosition(PRInt64 aTime); + + nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus(); + + // The decoder monitor must be obtained before modifying this state. + // NotifyAll on the monitor must be called when the state is changed by + // the main thread so the decoder thread can wake up. + // Accessed on state machine, audio, main, and AV thread. + State mState; + +private: + + // Waits on the decoder Monitor for aMs. If the decoder monitor is awoken + // by a Notify() call, we'll continue waiting, unless we've moved into + // shutdown state. This enables us to ensure that we wait for a specified + // time, and that the myriad of Notify()s we do an the decoder monitor + // don't cause the audio thread to be starved. The decoder monitor must + // be locked. + void Wait(PRUint32 aMs); + + // Dispatches an asynchronous event to update the media element's ready state. + void UpdateReadyState(); + + // Resets playback timing data. Called when we seek, on the state machine + // thread. + void ResetPlayback(); + + // Returns the audio clock, if we have audio, or -1 if we don't. + // Called on the state machine thread. + PRInt64 GetAudioClock(); + + // Returns the presentation time of the first sample or frame in the media. + // If the media has video, it returns the first video frame. The decoder + // monitor must be held with exactly one lock count. Called on the state + // machine thread. + VideoData* FindStartTime(); + + // Finds the end time of the last page in the Ogg file, storing the value + // in mEndTime if successful. The decoder must be held with exactly one lock + // count. Called on the state machine thread. + void FindEndTime(); + + // Performs YCbCr to RGB conversion, and pushes the image down the + // rendering pipeline. Called on the state machine thread. + void RenderVideoFrame(VideoData* aData); + + // If we have video, display a video frame if it's time for display has + // arrived, otherwise sleep until it's time for the next sample. Update + // the current frame time as appropriate, and trigger ready state update. + // The decoder monitor must be held with exactly one lock count. Called + // on the state machine thread. + void AdvanceFrame(); + + // Stops the decode threads. The decoder monitor must be held with exactly + // one lock count. Called on the state machine thread. + void StopDecodeThreads(); + + // Starts the decode threads. The decoder monitor must be held with exactly + // one lock count. Called on the state machine thread. + nsresult StartDecodeThreads(); + + // Reads the Ogg headers using the nsOggReader, and initializes playback. + // Called on the state machine thread. The decoder monitor must be held with + // exactly one lock count. + void LoadOggHeaders(); + + // The main loop for the audio thread. Sent to the thread as + // an NS_NEW_RUNNABLE_METHOD. This continually does blocking writes to + // to audio stream to play audio data. + void AudioLoop(); + + // Stop or pause playback of media. This has two modes, denoted by + // aMode being either AUDIO_PAUSE or AUDIO_SHUTDOWN. + // + // AUDIO_PAUSE: Suspends the audio stream to be resumed later. + // This does not close the OS based audio stream + // + // AUDIO_SHUTDOWN: Closes and destroys the audio stream and + // releases any OS resources. + // + // The decoder monitor must be held with exactly one lock count. Called + // on the state machine thread. + enum eStopMode {AUDIO_PAUSE, AUDIO_SHUTDOWN}; + void StopPlayback(eStopMode aMode); + + // Resume playback of media. Must be called with the decode monitor held. + // This resumes a paused audio stream. The decoder monitor must be held with + // exactly one lock count. Called on the state machine thread. + void StartPlayback(); + + // Returns PR_TRUE if we're currently playing. The decoder monitor must + // be held. + PRBool IsPlaying(); + + // Stores presentation info about required for playback of the media. + nsOggInfo mInfo; + + // Monitor on mAudioStream. This monitor must be held in order to delete + // or use the audio stream. This stops us destroying the audio stream + // while it's being used on another thread (typically when it's being + // written to on the audio thread). + Monitor mAudioMonitor; + + // The reader, don't call its methods with the decoder monitor held. + // This is created in the play state machine's constructor, and destroyed + // in the play state machine's destructor. + nsAutoPtr mReader; + + // The size of the decoded YCbCr frame. + // Accessed on state machine thread. + PRUint32 mCbCrSize; + + // Accessed on state machine thread. + nsAutoArrayPtr mCbCrBuffer; + + // Thread for pushing audio onto the audio hardware. + // The "audio push thread". + nsCOMPtr mAudioThread; + + // Thread for decoding video in background. The "decode thread". + nsCOMPtr mDecodeThread; + + // The time that playback started from the system clock. This is used + // for timing the display of audio frames when there's no audio. + // Accessed only via the state machine thread. + TimeStamp mPlayStartTime; + + // The amount of time we've spent playing already the media. The current + // playback position is therefore (mPlayDuration + (now - mPlayStartTime)). + // Accessed only via the state machine thread. + TimeDuration mPlayDuration; + + // Time that buffering started. Used for buffering timeout and only + // accessed on the state machine thread. + TimeStamp mBufferingStart; + + // Download position where we should stop buffering. Only + // accessed on the state machine thread. + PRInt64 mBufferingEndOffset; + + // Start time of the media, in milliseconds. This is the presentation + // time of the first sample decoded from the media, and is used to calculate + // duration and as a bounds for seeking. Accessed on state machine and + // main thread. Access controlled by decoder monitor. + PRInt64 mStartTime; + + // Time of the last page in the media, in milliseconds. This is the + // end time of the last sample in the media. Accessed on state + // machine and main thread. Access controlled by decoder monitor. + PRInt64 mEndTime; + + // Position to seek to in milliseconds when the seek state transition occurs. + // The decoder monitor lock must be obtained before reading or writing + // this value. Accessed on main and state machine thread. + PRInt64 mSeekTime; + + // The audio stream resource. Used on the state machine, audio, and main + // threads. You must hold the mAudioMonitor, and must NOT hold the decoder + // monitor when using the audio stream! + nsAutoPtr mAudioStream; + + // The time of the current frame in milliseconds. This is referenced from + // 0 which is the initial playback position. Set by the state machine + // thread, and read-only from the main thread to get the current + // time value. Synchronised via decoder monitor. + PRInt64 mCurrentFrameTime; + + // The presentation time of the first audio sample that was played. We can + // add this to the audio stream position to determine the current audio time. + // Accessed on audio and state machine thread. Synchronized by decoder monitor. + PRInt64 mAudioStartTime; + + // The end time of the last audio sample that's been pushed onto the audio + // hardware. This will approximately be the end time of the audio stream, + // unless another sample is pushed to the hardware. + PRInt64 mAudioEndTime; + + // The presentation time of the last video frame which has been displayed. + // Accessed from the state machine thread. + PRInt64 mVideoFrameTime; + + // Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written + // from the state machine and main threads. Synchronised via decoder + // monitor. + float mVolume; + + // PR_TRUE if the media resource can be seeked. Accessed from the state + // machine and main threads. Synchronised via decoder monitor. + PRPackedBool mSeekable; + + // PR_TRUE if an event to notify about a change in the playback + // position has been queued, but not yet run. It is set to PR_FALSE when + // the event is run. This allows coalescing of these events as they can be + // produced many times per second. Synchronised via decoder monitor. + // Accessed on main and state machine threads. + PRPackedBool mPositionChangeQueued; + + // PR_TRUE if the audio playback thread has finished. It is finished + // when either all the audio samples in the Vorbis bitstream have completed + // playing, or we've moved into shutdown state, and the threads are to be + // destroyed. Written by the audio playback thread and read and written by + // the state machine thread. Synchronised via decoder monitor. + PRPackedBool mAudioCompleted; + + // PR_TRUE if the decode thread has indicated that we need to buffer. + // Accessed by the decode thread and the state machine thread. + // Synchronised via the decoder monitor. + PRPackedBool mBufferExhausted; + + // PR_TRUE if mDuration has a value obtained from an HTTP header. + // Accessed on the state machine thread. + PRPackedBool mGotDurationFromHeader; + + // PR_FALSE while decode threads should be running. Accessed on audio, + // state machine and decode threads. Syncrhonised by decoder monitor. + PRPackedBool mStopDecodeThreads; +}; + + +#endif diff --git a/content/media/ogg/nsOggReader.cpp b/content/media/ogg/nsOggReader.cpp new file mode 100644 index 000000000000..b65bd0cf066f --- /dev/null +++ b/content/media/ogg/nsOggReader.cpp @@ -0,0 +1,1540 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +#include "nsISeekableStream.h" +#include "nsClassHashtable.h" +#include "nsTArray.h" +#include "nsOggDecoder.h" +#include "nsOggReader.h" +#include "nsOggCodecState.h" +#include "nsOggPlayStateMachine.h" +#include "mozilla/mozalloc.h" +#include "nsOggHacks.h" + +using mozilla::MonitorAutoExit; + +// Un-comment to enable logging of seek bisections. +//#define SEEK_LOGGING + +#ifdef PR_LOGGING +extern PRLogModuleInfo* gOggDecoderLog; +#define LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) +#ifdef SEEK_LOGGING +#define SEEK_LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) +#else +#define SEEK_LOG(type, msg) +#endif +#else +#define LOG(type, msg) +#define SEEK_LOG(type, msg) +#endif + +// Chunk size to read when reading Ogg files. Average Ogg page length +// is about 4300 bytes, so we read the file in chunks larger than that. +static const int PAGE_STEP = 8192; + +// 32 bit integer multiplication with overflow checking. Returns PR_TRUE +// if the multiplication was successful, or PR_FALSE if the operation resulted +// in an integer overflow. +PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult) { + PRUint64 a64 = a; + PRUint64 b64 = b; + PRUint64 r64 = a64 * b64; + if (r64 > PR_UINT32_MAX) + return PR_FALSE; + aResult = static_cast(r64); + return PR_TRUE; +} + +VideoData* VideoData::Create(PRInt64 aTime, + th_ycbcr_buffer aBuffer, + PRBool aKeyframe, + PRInt64 aGranulepos) +{ + nsAutoPtr v(new VideoData(aTime, aKeyframe, aGranulepos)); + for (PRUint32 i=0; i < 3; ++i) { + PRUint32 size = 0; + if (!MulOverflow32(PR_ABS(aBuffer[i].height), + PR_ABS(aBuffer[i].stride), + size)) + { + // Invalid frame size. Skip this plane. The plane will have 0 + // dimensions, thanks to our constructor. + continue; + } + unsigned char* p = static_cast(moz_xmalloc(size)); + if (!p) { + NS_WARNING("Failed to allocate memory for video frame"); + return nsnull; + } + v->mBuffer[i].data = p; + v->mBuffer[i].width = aBuffer[i].width; + v->mBuffer[i].height = aBuffer[i].height; + v->mBuffer[i].stride = aBuffer[i].stride; + memcpy(v->mBuffer[i].data, aBuffer[i].data, size); + } + return v.forget(); +} + +nsOggReader::nsOggReader(nsOggPlayStateMachine* aStateMachine) + : mMonitor("media.oggreader"), + mPlayer(aStateMachine), + mTheoraState(nsnull), + mVorbisState(nsnull), + mPageOffset(0), + mDataOffset(0), + mTheoraGranulepos(-1), + mVorbisGranulepos(-1), + mCallbackPeriod(0) +{ + MOZ_COUNT_CTOR(nsOggReader); +} + +nsOggReader::~nsOggReader() +{ + ResetDecode(); + ogg_sync_clear(&mOggState); + MOZ_COUNT_DTOR(nsOggReader); +} + +nsresult nsOggReader::Init() { + PRBool init = mCodecStates.Init(); + NS_ASSERTION(init, "Failed to initialize mCodecStates"); + if (!init) { + return NS_ERROR_FAILURE; + } + int ret = ogg_sync_init(&mOggState); + NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); + return NS_OK; +} + +nsresult nsOggReader::ResetDecode() +{ + nsresult res = NS_OK; + + // Clear the Theora/Vorbis granulepos capture status, so that the next + // decode calls recaptures the granulepos. + mTheoraGranulepos = -1; + mVorbisGranulepos = -1; + + mVideoQueue.Reset(); + mAudioQueue.Reset(); + + MonitorAutoEnter mon(mMonitor); + + // Discard any previously buffered packets/pages. + ogg_sync_reset(&mOggState); + if (mVorbisState && NS_FAILED(mVorbisState->Reset())) { + res = NS_ERROR_FAILURE; + } + if (mTheoraState && NS_FAILED(mTheoraState->Reset())) { + res = NS_ERROR_FAILURE; + } + + return res; +} + +nsresult nsOggReader::DecodeVorbis(nsTArray& aChunks, + ogg_packet* aPacket) +{ + // Successfully read a packet. + if (vorbis_synthesis(&mVorbisState->mBlock, aPacket) != 0) { + return NS_ERROR_FAILURE; + } + if (vorbis_synthesis_blockin(&mVorbisState->mDsp, + &mVorbisState->mBlock) != 0) + { + return NS_ERROR_FAILURE; + } + + float** pcm = 0; + PRUint32 samples = 0; + PRUint32 channels = mVorbisState->mInfo.channels; + while ((samples = vorbis_synthesis_pcmout(&mVorbisState->mDsp, &pcm)) > 0) { + if (samples > 0) { + float* buffer = new float[samples * channels]; + float* p = buffer; + for (PRUint32 i = 0; i < samples; ++i) { + for (PRUint32 j = 0; j < channels; ++j) { + *p++ = pcm[j][i]; + } + } + + PRInt64 duration = mVorbisState->Time((PRInt64)samples); + PRInt64 startTime = (mVorbisGranulepos != -1) ? + mVorbisState->Time(mVorbisGranulepos) : -1; + SoundData* s = new SoundData(startTime, + duration, + samples, + buffer, + channels); + if (mVorbisGranulepos != -1) { + mVorbisGranulepos += samples; + } + aChunks.AppendElement(s); + } + if (vorbis_synthesis_read(&mVorbisState->mDsp, samples) != 0) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +// Decode page, calculate timestamps. +PRBool nsOggReader::DecodeAudioPage() +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on playback or decode thread."); + NS_ASSERTION(mVorbisState!=0, "Need Vorbis state to decode audio"); + ogg_packet packet; + packet.granulepos = -1; + + PRBool endOfStream = PR_FALSE; + + nsAutoTArray chunks; + if (mVorbisGranulepos == -1) { + // Not captured Vorbis granulepos, read up until we get a granulepos, and + // back propagate the granulepos. + + // We buffer the packets' pcm samples until we reach a packet with a granulepos. + // This will be the last packet in a page. Then using that granulepos to + // calculate the packet's end time, we calculate all the packets' start times by + // subtracting their durations. + + // Ensure we've got Vorbis packets; read one more Vorbis page if necessary. + while (packet.granulepos <= 0 && !endOfStream) { + if (!ReadOggPacket(mVorbisState, &packet)) { + endOfStream = PR_TRUE; + break; + } + if (packet.e_o_s != 0) { + // This packet marks the logical end of the Vorbis bitstream. It may + // still contain sound samples, so we must still decode it. + endOfStream = PR_TRUE; + } + + if (NS_FAILED(DecodeVorbis(chunks, &packet))) { + NS_WARNING("Failed to decode Vorbis packet"); + } + } + + if (packet.granulepos > 0) { + // Successfully read up to a non -1 granulepos. + // Calculate the timestamps of the sound samples. + PRInt64 granulepos = packet.granulepos; // Represents end time of last sample. + mVorbisGranulepos = packet.granulepos; + for (int i = chunks.Length() - 1; i >= 0; --i) { + SoundData* s = chunks[i]; + PRInt64 startGranule = granulepos - s->mSamples; + s->mTime = mVorbisState->Time(startGranule); + granulepos = startGranule; + } + } + } else { + // We have already captured the granulepos. The next packet's granulepos + // is its number of samples, plus the previous granulepos. + if (!ReadOggPacket(mVorbisState, &packet)) { + endOfStream = PR_TRUE; + } else { + // Successfully read a packet from the file. Decode it. + endOfStream = packet.e_o_s != 0; + + // Try to decode any packet we've read. + if (NS_FAILED(DecodeVorbis(chunks, &packet))) { + NS_WARNING("Failed to decode Vorbis packet"); + } + + if (packet.granulepos != -1 && packet.granulepos != mVorbisGranulepos) { + // If the packet's granulepos doesn't match our running sample total, + // it's likely the bitstream has been damaged somehow, or perhaps + // oggz-chopped. Just assume the packet's granulepos is correct... + mVorbisGranulepos = packet.granulepos; + } + } + } + + // We've successfully decoded some sound chunks. Push them onto the audio + // queue. + for (PRUint32 i = 0; i < chunks.Length(); ++i) { + mAudioQueue.Push(chunks[i]); + } + + if (endOfStream) { + // We've encountered an end of bitstream packet, or we've hit the end of + // file while trying to decode, so inform the audio queue that there'll + // be no more samples. + mAudioQueue.Finish(); + return PR_FALSE; + } + + return PR_TRUE; +} + +// Returns 1 if the Theora info struct is decoding a media of Theora +// verion (maj,min,sub) or later, otherwise returns 0. +static int +TheoraVersion(th_info* info, + unsigned char maj, + unsigned char min, + unsigned char sub) +{ + ogg_uint32_t ver = (maj << 16) + (min << 8) + sub; + ogg_uint32_t th_ver = (info->version_major << 16) + + (info->version_minor << 8) + + info->version_subminor; + return (th_ver >= ver) ? 1 : 0; +} + +// Ensures that all the VideoData in aFrames array are stored in increasing +// order by timestamp. Used in assertions in debug builds. +static PRBool +AllFrameTimesIncrease(nsTArray& aFrames) +{ + PRInt64 prevTime = -1; + PRInt64 prevGranulepos = -1; + for (PRUint32 i = 0; i < aFrames.Length(); i++) { + VideoData* f = aFrames[i]; + if (f->mTime < prevTime) { + return PR_FALSE; + } + prevTime = f->mTime; + prevGranulepos = f->mGranulepos; + } + return PR_TRUE; +} + +static void Clear(nsTArray& aFrames) { + for (PRUint32 i = 0; i < aFrames.Length(); ++i) { + delete aFrames[i]; + } + aFrames.Clear(); +} + +nsresult nsOggReader::DecodeTheora(nsTArray& aFrames, + ogg_packet* aPacket) +{ + int ret = th_decode_packetin(mTheoraState->mCtx, aPacket, 0); + if (ret != 0 && ret != TH_DUPFRAME) { + return NS_ERROR_FAILURE; + } + PRInt64 time = (aPacket->granulepos != -1) + ? mTheoraState->StartTime(aPacket->granulepos) : -1; + if (ret == TH_DUPFRAME) { + aFrames.AppendElement(VideoData::CreateDuplicate(time, + aPacket->granulepos)); + } else if (ret == 0) { + th_ycbcr_buffer buffer; + ret = th_decode_ycbcr_out(mTheoraState->mCtx, buffer); + NS_ASSERTION(ret == 0, "th_decode_ycbcr_out failed"); + PRBool isKeyframe = th_packet_iskeyframe(aPacket) == 1; + VideoData *v = VideoData::Create(time, + buffer, + isKeyframe, + aPacket->granulepos); + if (!v) { + NS_WARNING("Failed to allocate memory for video frame"); + Clear(aFrames); + return NS_ERROR_OUT_OF_MEMORY; + } + aFrames.AppendElement(v); + } + return NS_OK; +} + +PRBool nsOggReader::DecodeVideoPage(PRBool &aKeyframeSkip, + PRInt64 aTimeThreshold) +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on state machine or AV thread."); + // We chose to keep track of the Theora granulepos ourselves, rather than + // rely on th_decode_packetin() to do it for us. This is because + // th_decode_packetin() simply works by incrementing a counter every time + // it's called, so if we drop frames and don't call it, subsequent granulepos + // will be wrong. Whenever we read a packet which has a granulepos, we use + // its granulepos, otherwise we increment the previous packet's granulepos. + + nsAutoTArray frames; + ogg_packet packet; + PRBool endOfStream = PR_FALSE; + if (mTheoraGranulepos == -1) { + // We've not read a Theora packet with a granulepos, so we don't know what + // timestamp to assign to Theora frames we decode. This will only happen + // the first time we read, or after a seek. We must read and buffer up to + // the first Theora packet with a granulepos, and back-propagate its + // granulepos to calculate the buffered frames' granulepos. + do { + if (!ReadOggPacket(mTheoraState, &packet)) { + // Failed to read another page, must be the end of file. We can't have + // already encountered an end of bitstream packet, else we wouldn't be + // here, so this bitstream must be missing its end of stream packet, or + // is otherwise corrupt (oggz-chop can output files like this). Inform + // the queue that there will be no more frames. + mVideoQueue.Finish(); + return PR_FALSE; + } + + if (packet.granulepos > 0) { + // We've found a packet with a granulepos, we can now determine the + // buffered packet's timestamps, as well as the timestamps for any + // packets we read subsequently. + mTheoraGranulepos = packet.granulepos; + } + + if (DecodeTheora(frames, &packet) == NS_ERROR_OUT_OF_MEMORY) { + NS_WARNING("Theora decode memory allocation failure!"); + return PR_FALSE; + } + + } while (packet.granulepos <= 0 && !endOfStream); + + if (packet.granulepos > 0) { + // We have captured a granulepos. Backpropagate the granulepos + // to determine buffered packets' timestamps. + PRInt64 succGranulepos = packet.granulepos; + int version_3_2_1 = TheoraVersion(&mTheoraState->mInfo,3,2,1); + int shift = mTheoraState->mInfo.keyframe_granule_shift; + for (int i = frames.Length() - 2; i >= 0; --i) { + PRInt64 granulepos = succGranulepos; + if (frames[i]->mKeyframe) { + // This frame is a keyframe. It's granulepos is the previous granule + // number minus 1, shifted by granuleshift. + ogg_int64_t frame_index = th_granule_frame(mTheoraState->mCtx, + granulepos); + granulepos = (frame_index + version_3_2_1 - 1) << shift; + // Theora 3.2.1+ granulepos store frame number [1..N], so granulepos + // should be > 0. + // Theora 3.2.0 granulepos store the frame index [0..(N-1)], so + // granulepos should be >= 0. + NS_ASSERTION((version_3_2_1 && granulepos > 0) || + granulepos >= 0, "Should have positive granulepos"); + } else { + // Packet is not a keyframe. It's granulepos depends on its successor + // packet... + if (frames[i+1]->mKeyframe) { + // The successor frame is a keyframe, so we can't just subtract 1 + // from the "keyframe offset" part of its granulepos, as it + // doesn't have one! So fake it, take the keyframe offset as the + // max possible keyframe offset. This means the granulepos (probably) + // overshoots and claims that it depends on a frame before its actual + // keyframe but at least its granule number will be correct, so the + // times we calculate from this granulepos will also be correct. + ogg_int64_t frameno = th_granule_frame(mTheoraState->mCtx, + granulepos); + ogg_int64_t max_offset = NS_MIN((frameno - 1), + (ogg_int64_t)(1 << shift) - 1); + ogg_int64_t granule = frameno + + TheoraVersion(&mTheoraState->mInfo,3,2,1) - + 1 - max_offset; + NS_ASSERTION(granule > 0, "Must have positive granulepos"); + granulepos = (granule << shift) + max_offset; + } else { + // Neither previous nor this frame are keyframes, so we can just + // decrement the previous granulepos to calculate this frames + // granulepos. + --granulepos; + } + } + // Check that the frame's granule number (it's frame number) is + // one less than the successor frame. + NS_ASSERTION(th_granule_frame(mTheoraState->mCtx, succGranulepos) == + th_granule_frame(mTheoraState->mCtx, granulepos) + 1, + "Granulepos calculation is incorrect!"); + frames[i]->mTime = mTheoraState->StartTime(granulepos); + frames[i]->mGranulepos = granulepos; + succGranulepos = granulepos; + NS_ASSERTION(frames[i]->mTime < frames[i+1]->mTime, "Times should increase"); + } + NS_ASSERTION(AllFrameTimesIncrease(frames), "All frames must have granulepos"); + } + } else { + + NS_ASSERTION(mTheoraGranulepos > 0, "We must Theora granulepos!"); + + if (!ReadOggPacket(mTheoraState, &packet)) { + // Failed to read from file, so EOF or other premature failure. + // Inform the queue that there will be no more frames. + mVideoQueue.Finish(); + return PR_FALSE; + } + + endOfStream = packet.e_o_s != 0; + + // Maintain the Theora granulepos. We must do this even if we drop frames, + // otherwise our clock will be wrong after we've skipped frames. + if (packet.granulepos != -1) { + // Incoming packet has a granulepos, use that as it's granulepos. + mTheoraGranulepos = packet.granulepos; + } else { + // Increment the previous Theora granulepos. + PRInt64 granulepos = 0; + int shift = mTheoraState->mInfo.keyframe_granule_shift; + // Theora 3.2.1+ bitstreams granulepos store frame number; [1..N] + // Theora 3.2.0 bitstreams store the frame index; [0..(N-1)] + if (!th_packet_iskeyframe(&packet)) { + granulepos = mTheoraGranulepos + 1; + } else { + ogg_int64_t frameindex = th_granule_frame(mTheoraState->mCtx, + mTheoraGranulepos); + ogg_int64_t granule = frameindex + + TheoraVersion(&mTheoraState->mInfo,3,2,1) + 1; + NS_ASSERTION(granule > 0, "Must have positive granulepos"); + granulepos = granule << shift; + } + + NS_ASSERTION(th_granule_frame(mTheoraState->mCtx, mTheoraGranulepos) + 1 == + th_granule_frame(mTheoraState->mCtx, granulepos), + "Frame number must increment by 1"); + packet.granulepos = mTheoraGranulepos = granulepos; + } + + PRInt64 time = mTheoraState->StartTime(mTheoraGranulepos); + NS_ASSERTION(packet.granulepos != -1, "Must know packet granulepos"); + if (!aKeyframeSkip || + (th_packet_iskeyframe(&packet) == 1 && time >= aTimeThreshold)) + { + if (DecodeTheora(frames, &packet) == NS_ERROR_OUT_OF_MEMORY) { + NS_WARNING("Theora decode memory allocation failure"); + return PR_FALSE; + } + } + } + + // Push decoded data into the video frame queue. + for (PRUint32 i = 0; i < frames.Length(); i++) { + nsAutoPtr data(frames[i]); + if (!aKeyframeSkip || (aKeyframeSkip && frames[i]->mKeyframe)) { + mVideoQueue.Push(data.forget()); + if (aKeyframeSkip && frames[i]->mKeyframe) { + aKeyframeSkip = PR_FALSE; + } + } else { + frames[i] = nsnull; + data = nsnull; + } + } + + if (endOfStream) { + // We've encountered an end of bitstream packet. Inform the queue that + // there will be no more frames. + mVideoQueue.Finish(); + } + + return !endOfStream; +} + +nsresult nsOggReader::GetBufferedBytes(nsTArray& aRanges) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + mMonitor.AssertCurrentThreadIn(); + PRInt64 startOffset = mDataOffset; + nsMediaStream* stream = mPlayer->mDecoder->mStream; + while (PR_TRUE) { + PRInt64 endOffset = stream->GetCachedDataEnd(startOffset); + if (endOffset == startOffset) { + // Uncached at startOffset. + endOffset = stream->GetNextCachedData(startOffset); + if (endOffset == -1) { + // Uncached at startOffset until endOffset of stream, or we're at + // the end of stream. + break; + } + } else { + // Bytes [startOffset..endOffset] are cached. + PRInt64 startTime = -1; + PRInt64 endTime = -1; + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + FindStartTime(startOffset, startTime); + if (startTime != -1 && + (endTime = FindEndTime(endOffset) != -1)) + { + aRanges.AppendElement(ByteRange(startOffset, + endOffset, + startTime, + endTime)); + } + } + startOffset = endOffset; + } + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +ByteRange +nsOggReader::GetSeekRange(const nsTArray& ranges, + PRInt64 aTarget, + PRInt64 aStartTime, + PRInt64 aEndTime, + PRBool aExact) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + PRInt64 so = mDataOffset; + PRInt64 eo = mPlayer->mDecoder->mStream->GetLength(); + PRInt64 st = aStartTime; + PRInt64 et = aEndTime; + for (PRUint32 i = 0; i < ranges.Length(); i++) { + const ByteRange &r = ranges[i]; + if (r.mTimeStart < aTarget) { + so = r.mOffsetStart; + st = r.mTimeStart; + } + if (r.mTimeEnd >= aTarget && r.mTimeEnd < et) { + eo = r.mOffsetEnd; + et = r.mTimeEnd; + } + + if (r.mTimeStart < aTarget && aTarget <= r.mTimeEnd) { + // Target lies exactly in this range. + return ranges[i]; + } + } + return aExact ? ByteRange() : ByteRange(so, eo, st, et); +} + +nsresult nsOggReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTime) +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mPlayer->mDecoder, aTarget)); + nsMediaStream* stream = mPlayer->mDecoder->mStream; + + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + if (aTarget == aStartTime) { + stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset); + mPageOffset = mDataOffset; + NS_ASSERTION(aStartTime != -1, "mStartTime should be known"); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + mPlayer->UpdatePlaybackPosition(aStartTime); + } + } else { + + // Determine the already downloaded data in the media cache. + nsAutoTArray ranges; + stream->Pin(); + if (NS_FAILED(GetBufferedBytes(ranges))) { + stream->Unpin(); + return NS_ERROR_FAILURE; + } + + // Try to seek in the cached data ranges first, before falling back to + // seeking over the network. This makes seeking in buffered ranges almost + // instantaneous. + ByteRange r = GetSeekRange(ranges, aTarget, aStartTime, aEndTime, PR_TRUE); + nsresult res = NS_ERROR_FAILURE; + if (!r.IsNull()) { + // The frame should be in this buffered range. Seek exactly there. + res = SeekBisection(aTarget, r, 0); + + if (NS_SUCCEEDED(res) && HasVideo()) { + // We have an active Theora bitstream. Decode the next Theora frame, and + // extract its keyframe's time. + PRBool eof; + do { + PRBool skip = PR_FALSE; + eof = !DecodeVideoPage(skip, 0); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + stream->Unpin(); + return NS_ERROR_FAILURE; + } + } + } while (!eof && + mVideoQueue.GetSize() == 0); + + VideoData* video = mVideoQueue.PeekFront(); + if (video && !video->mKeyframe) { + // First decoded frame isn't a keyframe, seek back to previous keyframe, + // otherwise we'll get visual artifacts. + NS_ASSERTION(video->mGranulepos != -1, "Must have a granulepos"); + int shift = mTheoraState->mInfo.keyframe_granule_shift; + PRInt64 keyframeGranulepos = (video->mGranulepos >> shift) << shift; + PRInt64 keyframeTime = mTheoraState->StartTime(keyframeGranulepos); + + SEEK_LOG(PR_LOG_DEBUG, ("Keyframe for %lld is at %lld, seeking back to it", + video->mTime, keyframeTime)); + ByteRange k = GetSeekRange(ranges, + keyframeTime, + aStartTime, + aEndTime, + PR_FALSE); + res = SeekBisection(keyframeTime, k, 500); + NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode"); + NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode"); + } + } + } + + stream->Unpin(); + + if (NS_FAILED(res)) { + // We failed to find the seek target (or perhaps its keyframe, somehow?) + // in a buffered range. Minimize the bisection search space using the + // buffered ranges, and perform a bisection search. + + // If we've got an active Theora bitstream, determine the maximum possible + // time in ms which a keyframe could be before a given interframe. We + // subtract this from our seek target, seek to the new target, and then + // decode forwards to the original seek target. We should encounter a + // keyframe in that interval. This prevents us from needing to run two + // bisections; one for the seek target frame, and another to find its + // keyframe. It's usually faster to just download this extra data, rather + // tham perform two bisections to find the seek target's keyframe. We + // don't do this offsetting when seeking in a buffered ranges (above), + // as the extra decoding causes a noticable speed hit when all the data + // is buffered. + PRInt64 keyframeOffsetMs = 0; + if (HasVideo() && mTheoraState) { + keyframeOffsetMs = mTheoraState->MaxKeyframeOffset(); + } + PRInt64 seekTarget = NS_MAX(aStartTime, aTarget - keyframeOffsetMs); + + ByteRange k = GetSeekRange(ranges, seekTarget, aStartTime, aEndTime, PR_FALSE); + res = SeekBisection(seekTarget, k, 500); + + NS_ENSURE_SUCCESS(res, res); + NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode"); + NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode"); + } + } + + // Decode forward to the seek target frame. Start with video, if we have it. + // We should pass a keyframe while doing this. + if (HasVideo()) { + nsAutoPtr video; + PRBool eof = PR_FALSE; + PRInt64 startTime = -1; + video = nsnull; + while (HasVideo() && !eof) { + while (mVideoQueue.GetSize() == 0 && !eof) { + PRBool skip = PR_FALSE; + eof = !DecodeVideoPage(skip, 0); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return NS_ERROR_FAILURE; + } + } + } + if (mVideoQueue.GetSize() == 0) { + break; + } + video = mVideoQueue.PeekFront(); + // If the frame end time is less than the seek target, we won't want + // to display this frame after the seek, so discard it. + if (video && video->mTime + mCallbackPeriod < aTarget) { + if (startTime == -1) { + startTime = video->mTime; + } + mVideoQueue.PopFront(); + video = nsnull; + } else { + video.forget(); + break; + } + } + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return NS_ERROR_FAILURE; + } + } + SEEK_LOG(PR_LOG_DEBUG, ("First video frame after decode is %lld", startTime)); + } + + if (HasAudio()) { + // Decode audio forward to the seek target. + nsAutoPtr audio; + bool eof = PR_FALSE; + while (HasAudio() && !eof) { + while (!eof && mAudioQueue.GetSize() == 0) { + eof = !DecodeAudioPage(); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return NS_ERROR_FAILURE; + } + } + } + audio = mAudioQueue.PeekFront(); + if (audio && audio->mTime + audio->mDuration <= aTarget) { + mAudioQueue.PopFront(); + audio = nsnull; + } else { + audio.forget(); + break; + } + } + } + + return NS_OK; +} + +enum PageSyncResult { + PAGE_SYNC_ERROR = 1, + PAGE_SYNC_END_OF_RANGE= 2, + PAGE_SYNC_OK = 3 +}; + +// Reads a page from the media stream. +static PageSyncResult +PageSync(ogg_sync_state* aState, + nsMediaStream* aStream, + PRInt64 aEndOffset, + ogg_page* aPage, + int& aSkippedBytes) +{ + aSkippedBytes = 0; + // Sync to the next page. + int ret = 0; + PRUint32 bytesRead = 0; + while (ret <= 0) { + ret = ogg_sync_pageseek(aState, aPage); + if (ret == 0) { + char* buffer = ogg_sync_buffer(aState, PAGE_STEP); + NS_ASSERTION(buffer, "Must have a buffer"); + + // Read from the file into the buffer + PRInt64 bytesToRead = NS_MIN(static_cast(PAGE_STEP), + aEndOffset - aStream->Tell()); + if (bytesToRead <= 0) { + return PAGE_SYNC_END_OF_RANGE; + } + nsresult rv = aStream->Read(buffer, + static_cast(bytesToRead), + &bytesRead); + if (NS_FAILED(rv)) { + return PAGE_SYNC_ERROR; + } + + if (bytesRead == 0 && NS_SUCCEEDED(rv)) { + // End of file. + return PAGE_SYNC_END_OF_RANGE; + } + + // Update the synchronisation layer with the number + // of bytes written to the buffer + ret = ogg_sync_wrote(aState, bytesRead); + NS_ENSURE_TRUE(ret == 0, PAGE_SYNC_ERROR); + continue; + } + + if (ret < 0) { + NS_ASSERTION(aSkippedBytes >= 0, "Offset >= 0"); + aSkippedBytes += -ret; + NS_ASSERTION(aSkippedBytes >= 0, "Offset >= 0"); + continue; + } + } + + return PAGE_SYNC_OK; +} + +nsresult nsOggReader::SeekBisection(PRInt64 aTarget, + const ByteRange& aRange, + PRUint32 aFuzz) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + nsMediaStream* stream = mPlayer->mDecoder->mStream; + + if (aTarget == aRange.mTimeStart) { + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset); + mPageOffset = mDataOffset; + return NS_OK; + } + + // Bisection search, find start offset of last page with end time less than + // the seek target. + ogg_int64_t startOffset = aRange.mOffsetStart; + ogg_int64_t startTime = aRange.mTimeStart; + ogg_int64_t startLength = 0; + ogg_int64_t endOffset = aRange.mOffsetEnd; + ogg_int64_t endTime = aRange.mTimeEnd; + + ogg_int64_t seekTarget = aTarget; + PRInt64 seekLowerBound = NS_MAX(static_cast(0), aTarget - aFuzz); + int hops = 0; + ogg_int64_t previousGuess = -1; + int backsteps = 1; + const int maxBackStep = 10; + NS_ASSERTION(static_cast(PAGE_STEP) * pow(2.0, maxBackStep) < PR_INT32_MAX, + "Backstep calculation must not overflow"); + while (PR_TRUE) { + ogg_int64_t duration = 0; + double target = 0; + ogg_int64_t interval = 0; + ogg_int64_t guess = 0; + ogg_page page; + int skippedBytes = 0; + ogg_int64_t pageOffset = 0; + ogg_int64_t pageLength = 0; + int backoff = 0; + ogg_int64_t granuleTime = -1; + PRInt64 oldPageOffset = 0; + + // Guess where we should bisect to, based on the bit rate and the time + // remaining in the interval. + while (PR_TRUE) { + + // Discard any previously buffered packets/pages. + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + + // Guess bisection point. + duration = endTime - startTime; + target = (double)(seekTarget - startTime) / (double)duration; + interval = endOffset - startOffset - startLength; + guess = startOffset + startLength + + (ogg_int64_t)((double)interval * target) - backoff; + guess = NS_MIN(guess, endOffset - PAGE_STEP); + guess = NS_MAX(guess, startOffset + startLength); + + if (interval == 0 || guess == previousGuess) { + interval = 0; + // Our interval is empty, we've found the optimal seek point, as the + // start page is before the seek target, and the end page after the + // seek target. + break; + } + + NS_ASSERTION(guess >= startOffset + startLength, "Guess must be after range start"); + NS_ASSERTION(guess < endOffset, "Guess must be before range end"); + NS_ASSERTION(guess != previousGuess, "Guess should be differnt to previous"); + previousGuess = guess; + + SEEK_LOG(PR_LOG_DEBUG, ("Seek loop offset_start=%lld start_end=%lld " + "offset_guess=%lld offset_end=%lld interval=%lld " + "target=%lf time_start=%lld time_end=%lld", + startOffset, (startOffset+startLength), guess, + endOffset, interval, target, startTime, endTime)); + hops++; + stream->Seek(nsISeekableStream::NS_SEEK_SET, guess); + + // We've seeked into the media somewhere. Locate the next page, and then + // figure out the granule time of the audio and video bitstreams there. + // We can then make a bisection decision based on our location in the media. + + PageSyncResult res = PageSync(&mOggState, + stream, + endOffset, + &page, + skippedBytes); + if (res == PAGE_SYNC_ERROR) { + return NS_ERROR_FAILURE; + } + + // We've located a page of length |ret| at |guess + skippedBytes|. + // Remember where the page is located. + pageOffset = guess + skippedBytes; + pageLength = page.header_len + page.body_len; + mPageOffset = pageOffset + pageLength; + + if (mPageOffset == endOffset || res == PAGE_SYNC_END_OF_RANGE) { + // Our guess was too close to the end, we've ended up reading the end + // page. Backoff exponentially from the end point, in case the last + // page/frame/sample is huge. + backsteps = NS_MIN(backsteps + 1, maxBackStep); + backoff = PAGE_STEP * pow(2.0, backsteps); + continue; + } + + NS_ASSERTION(mPageOffset < endOffset, "Page read cursor should be inside range"); + + // Read pages until we can determine the granule time of the audio and + // video bitstream. + ogg_int64_t audioTime = -1; + ogg_int64_t videoTime = -1; + int ret; + oldPageOffset = mPageOffset; + while ((mVorbisState && audioTime == -1) || + (mTheoraState && videoTime == -1)) { + + // Add the page to its codec state, determine its granule time. + PRUint32 serial = ogg_page_serialno(&page); + nsOggCodecState* codecState = nsnull; + mCodecStates.Get(serial, &codecState); + if (codecState && codecState->mActive) { + ret = ogg_stream_pagein(&codecState->mState, &page); + NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); + } + + ogg_int64_t granulepos = ogg_page_granulepos(&page); + + if (HasAudio() && + granulepos != -1 && + serial == mVorbisState->mSerial && + audioTime == -1) { + audioTime = mVorbisState->Time(granulepos); + } + + if (HasVideo() && + granulepos != -1 && + serial == mTheoraState->mSerial && + videoTime == -1) { + videoTime = mTheoraState->StartTime(granulepos); + } + + mPageOffset += page.header_len + page.body_len; + if (ReadOggPage(&page) == -1) { + break; + } + } + + if ((HasAudio() && audioTime == -1) || + (HasVideo() && videoTime == -1)) + { + backsteps = NS_MIN(backsteps + 1, maxBackStep); + backoff = PAGE_STEP * pow(2.0, backsteps); + continue; + } + + // We've found appropriate time stamps here. Proceed to bisect + // the search space. + granuleTime = NS_MAX(audioTime, videoTime); + NS_ASSERTION(granuleTime > 0, "Must get a granuletime"); + break; + } + + if (interval == 0) { + // Seek termination condition; we've found the page boundary of the + // last page before the target, and the first page after the target. + SEEK_LOG(PR_LOG_DEBUG, ("Seek loop (interval == 0) break")); + NS_ASSERTION(startTime < aTarget, "Start time must always be less than target"); + stream->Seek(nsISeekableStream::NS_SEEK_SET, startOffset); + mPageOffset = startOffset; + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + break; + } + + SEEK_LOG(PR_LOG_DEBUG, ("Time at offset %lld is %lldms", guess, granuleTime)); + if (granuleTime < seekTarget && granuleTime > seekLowerBound) { + // We're within the fuzzy region in which we want to terminate the search. + stream->Seek(nsISeekableStream::NS_SEEK_SET, oldPageOffset); + mPageOffset = oldPageOffset; + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + break; + } + + if (granuleTime >= seekTarget) { + // We've landed after the seek target. + ogg_int64_t old_offset_end = endOffset; + endOffset = pageOffset; + NS_ASSERTION(endOffset < old_offset_end, "offset_end must decrease"); + endTime = granuleTime; + } else if (granuleTime < seekTarget) { + // Landed before seek target. + ogg_int64_t old_offset_start = startOffset; + startOffset = pageOffset; + startLength = pageLength; + NS_ASSERTION(startOffset > old_offset_start, "offset_start must increase"); + startTime = granuleTime; + } + NS_ASSERTION(startTime < seekTarget, "Must be before seek target"); + NS_ASSERTION(endTime >= seekTarget, "End must be after seek target"); + } + + SEEK_LOG(PR_LOG_DEBUG, ("Seek complete in %d bisections.", hops)); + + return NS_OK; +} + +PRInt64 nsOggReader::ReadOggPage(ogg_page* aPage) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on play state machine or decode thread."); + mMonitor.AssertCurrentThreadIn(); + + int ret = 0; + while((ret = ogg_sync_pageseek(&mOggState, aPage)) <= 0) { + if (ret < 0) { + // Lost page sync, have to skip up to next page. + mPageOffset += -ret; + continue; + } + // Returns a buffer that can be written too + // with the given size. This buffer is stored + // in the ogg synchronisation structure. + char* buffer = ogg_sync_buffer(&mOggState, 4096); + NS_ASSERTION(buffer, "ogg_sync_buffer failed"); + + // Read from the stream into the buffer + PRUint32 bytesRead = 0; + + nsresult rv = mPlayer->mDecoder->mStream->Read(buffer, 4096, &bytesRead); + if (NS_FAILED(rv) || (bytesRead == 0 && ret == 0)) { + // End of file. + return -1; + } + + mPlayer->mDecoder->NotifyBytesConsumed(bytesRead); + // Update the synchronisation layer with the number + // of bytes written to the buffer + ret = ogg_sync_wrote(&mOggState, bytesRead); + NS_ENSURE_TRUE(ret == 0, -1); + } + PRInt64 offset = mPageOffset; + mPageOffset += aPage->header_len + aPage->body_len; + + return offset; +} + +PRBool nsOggReader::ReadOggPacket(nsOggCodecState* aCodecState, + ogg_packet* aPacket) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on play state machine or decode thread."); + mMonitor.AssertCurrentThreadIn(); + + if (!aCodecState || !aCodecState->mActive) { + return PR_FALSE; + } + + int ret = 0; + while ((ret = ogg_stream_packetout(&aCodecState->mState, aPacket)) != 1) { + ogg_page page; + + if (aCodecState->PageInFromBuffer()) { + // The codec state has inserted a previously buffered page into its + // ogg_stream_state, no need to read a page from the channel. + continue; + } + + // The codec state does not have any buffered pages, so try to read another + // page from the channel. + if (ReadOggPage(&page) == -1) { + return PR_FALSE; + } + + PRUint32 serial = ogg_page_serialno(&page); + nsOggCodecState* codecState = nsnull; + mCodecStates.Get(serial, &codecState); + + if (serial == aCodecState->mSerial) { + // This page is from our target bitstream, insert it into the + // codec state's ogg_stream_state so we can read a packet. + ret = ogg_stream_pagein(&codecState->mState, &page); + NS_ENSURE_TRUE(ret == 0, PR_FALSE); + } else if (codecState && codecState->mActive) { + // Page is for another active bitstream, add the page to its codec + // state's buffer for later consumption when that stream next tries + // to read a packet. + codecState->AddToBuffer(&page); + } + } + + return PR_TRUE; +} + +// Returns PR_TRUE when all bitstreams in aBitstreams array have finished +// reading their headers. +static PRBool DoneReadingHeaders(nsTArray& aBitstreams) { + for (PRUint32 i = 0; i < aBitstreams .Length(); i++) { + if (!aBitstreams [i]->DoneReadingHeaders()) { + return PR_FALSE; + } + } + return PR_TRUE; +} + +nsresult nsOggReader::ReadOggHeaders(nsOggInfo& aInfo) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), "Should be on play state machine thread."); + MonitorAutoEnter mon(mMonitor); + + // We read packets until all bitstreams have read all their header packets. + // We record the offset of the first non-header page so that we know + // what page to seek to when seeking to the media start. + + ogg_page page; + PRInt64 pageOffset; + nsAutoTArray bitstreams; + PRBool readAllBOS = PR_FALSE; + mDataOffset = 0; + while (PR_TRUE) { + if (readAllBOS && DoneReadingHeaders(bitstreams)) { + if (mDataOffset == 0) { + // We've previously found the start of the first non-header packet. + mDataOffset = mPageOffset; + } + break; + } + pageOffset = ReadOggPage(&page); + if (pageOffset == -1) { + // Some kind of error... + break; + } + + int ret = 0; + int serial = ogg_page_serialno(&page); + nsOggCodecState* codecState = 0; + + if (ogg_page_bos(&page)) { + NS_ASSERTION(!readAllBOS, "We shouldn't encounter another BOS page"); + codecState = nsOggCodecState::Create(&page); + PRBool r = mCodecStates.Put(serial, codecState); + NS_ASSERTION(r, "Failed to insert into mCodecStates"); + bitstreams.AppendElement(codecState); + if (codecState && + codecState->GetType() == nsOggCodecState::TYPE_VORBIS && + !mVorbisState) + { + // First Vorbis bitstream, we'll play this one. Subsequent Vorbis + // bitstreams will be ignored. + mVorbisState = static_cast(codecState); + } + if (codecState && + codecState->GetType() == nsOggCodecState::TYPE_THEORA && + !mTheoraState) + { + // First Theora bitstream, we'll play this one. Subsequent Theora + // bitstreams will be ignored. + mTheoraState = static_cast(codecState); + } + } else { + // We've encountered the a non Beginning Of Stream page. No more + // BOS pages can follow in this Ogg segment, so there will be no other + // bitstreams in the Ogg (unless it's invalid). + readAllBOS = PR_TRUE; + } + + mCodecStates.Get(serial, &codecState); + NS_ENSURE_TRUE(codecState, NS_ERROR_FAILURE); + + // Add a complete page to the bitstream + ret = ogg_stream_pagein(&codecState->mState, &page); + NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); + + // Process all available header packets in the stream. + ogg_packet packet; + if (codecState->DoneReadingHeaders() && mDataOffset == 0) + { + // Stream has read all header packets, but now there's more data in + // (presumably) a non-header page, we must have finished header packets. + // This can happen in incorrectly chopped streams. + mDataOffset = pageOffset; + continue; + } + while (!codecState->DoneReadingHeaders() && + (ret = ogg_stream_packetout(&codecState->mState, &packet)) != 0) + { + if (ret == -1) { + // Sync lost, we've probably encountered the continuation of a packet + // in a chopped video. + continue; + } + // A packet is available. If it is not a header packet we'll break. + // If it is a header packet, process it as normal. + codecState->DecodeHeader(&packet); + } + if (ogg_stream_packetpeek(&codecState->mState, &packet) != 0 && + mDataOffset == 0) + { + // We're finished reading headers for this bitstream, but there's still + // packets in the bitstream to read. The bitstream is probably poorly + // muxed, and includes the last header packet on a page with non-header + // packets. We need to ensure that this is the media start page offset. + mDataOffset = pageOffset; + } + } + // Deactivate any non-primary bitstreams. + for (PRUint32 i = 0; i < bitstreams.Length(); i++) { + nsOggCodecState* s = bitstreams[i]; + if (s != mVorbisState && s != mTheoraState) { + s->Deactivate(); + } + } + + // Initialize the first Theora and Vorbis bitstreams. According to the + // Theora spec these can be considered the 'primary' bitstreams for playback. + // Extract the metadata needed from these streams. + float aspectRatio = 0; + if (mTheoraState) { + if (mTheoraState->Init()) { + mCallbackPeriod = mTheoraState->mFrameDuration; + aspectRatio = mTheoraState->mAspectRatio; + gfxIntSize sz(mTheoraState->mInfo.pic_width, + mTheoraState->mInfo.pic_height); + mPlayer->mDecoder->SetVideoData(sz, mTheoraState->mAspectRatio, nsnull); + } else { + mTheoraState = nsnull; + } + } + if (mVorbisState) { + mVorbisState->Init(); + } + + aInfo.mHasAudio = HasAudio(); + aInfo.mHasVideo = HasVideo(); + aInfo.mCallbackPeriod = mCallbackPeriod; + if (HasAudio()) { + aInfo.mAudioRate = mVorbisState->mInfo.rate; + aInfo.mAudioChannels = mVorbisState->mInfo.channels; + } + if (HasVideo()) { + aInfo.mFramerate = mTheoraState->mFrameRate; + aInfo.mAspectRatio = mTheoraState->mAspectRatio; + aInfo.mPicture.width = mTheoraState->mInfo.pic_width; + aInfo.mPicture.height = mTheoraState->mInfo.pic_height; + aInfo.mPicture.x = mTheoraState->mInfo.pic_x; + aInfo.mPicture.y = mTheoraState->mInfo.pic_y; + aInfo.mFrame.width = mTheoraState->mInfo.frame_width; + aInfo.mFrame.height = mTheoraState->mInfo.frame_height; + } + aInfo.mDataOffset = mDataOffset; + + LOG(PR_LOG_DEBUG, ("Done loading headers, data offset %lld", mDataOffset)); + + return NS_OK; +} + +template +Data* nsOggReader::DecodeToFirstData(DecodeFn aDecodeFn, + MediaQueue& aQueue) +{ + PRBool eof = PR_FALSE; + while (!eof && aQueue.GetSize() == 0) { + { + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return nsnull; + } + } + eof = !(this->*aDecodeFn)(); + } + Data* d = nsnull; + return (d = aQueue.PeekFront()) ? d : nsnull; +} + +VideoData* nsOggReader::FindStartTime(PRInt64 aOffset, + PRInt64& aOutStartTime) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), "Should be on state machine thread."); + + nsMediaStream* stream = mPlayer->mDecoder->mStream; + + stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset); + if (NS_FAILED(ResetDecode())) { + return nsnull; + } + + // Extract the start times of the bitstreams in order to calculate + // the duration. + PRInt64 videoStartTime = PR_INT64_MAX; + PRInt64 audioStartTime = PR_INT64_MAX; + VideoData* videoData = nsnull; + + if (HasVideo()) { + videoData = DecodeToFirstData(&nsOggReader::DecodeVideoPage, + mVideoQueue); + if (videoData) { + videoStartTime = videoData->mTime; + } + } + if (HasAudio()) { + SoundData* soundData = DecodeToFirstData(&nsOggReader::DecodeAudioPage, + mAudioQueue); + if (soundData) { + audioStartTime = soundData->mTime; + } + } + + PRInt64 startTime = PR_MIN(videoStartTime, audioStartTime); + if (startTime != PR_INT64_MAX) { + aOutStartTime = startTime; + } + + return videoData; +} + +// Returns an ogg page's checksum. +static ogg_uint32_t +GetChecksum(ogg_page* page) +{ + if (page == 0 || page->header == 0 || page->header_len < 25) { + return 0; + } + const unsigned char* p = page->header + 22; + PRUint32 c = p[0] + + (p[1] << 8) + + (p[2] << 16) + + (p[3] << 24); + return c; +} + +PRInt64 nsOggReader::FindEndTime(PRInt64 aEndOffset) +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread(), "Should be on state machine thread."); + + nsMediaStream* stream = mPlayer->mDecoder->mStream; + ogg_sync_reset(&mOggState); + + stream->Seek(nsISeekableStream::NS_SEEK_SET, aEndOffset); + + // We need to find the last page which ends before aEndOffset that + // has a granulepos that we can convert to a timestamp. We do this by + // backing off from aEndOffset until we encounter a page on which we can + // interpret the granulepos. If while backing off we encounter a page which + // we've previously encountered before, we'll either backoff again if we + // haven't found an end time yet, or return the last end time found. + const int step = 5000; + PRInt64 offset = aEndOffset; + PRInt64 endTime = -1; + PRUint32 checksumAfterSeek = 0; + PRUint32 prevChecksumAfterSeek = 0; + PRBool mustBackOff = PR_FALSE; + while (PR_TRUE) { + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return -1; + } + } + ogg_page page; + int ret = ogg_sync_pageseek(&mOggState, &page); + if (ret == 0) { + // We need more data if we've not encountered a page we've seen before, + // or we've read to the end of file. + if (mustBackOff || stream->Tell() == aEndOffset) { + if (endTime != -1) { + // We have encountered a page before, or we're at the end of file. + break; + } + mustBackOff = PR_FALSE; + prevChecksumAfterSeek = checksumAfterSeek; + checksumAfterSeek = 0; + ogg_sync_reset(&mOggState); + offset = NS_MAX(static_cast(0), offset - step); + stream->Seek(nsISeekableStream::NS_SEEK_SET, offset); + } + NS_ASSERTION(stream->Tell() < aEndOffset, + "Stream pos must be before range end"); + + PRInt64 limit = NS_MIN(static_cast(PR_UINT32_MAX), + aEndOffset - stream->Tell()); + limit = NS_MAX(static_cast(0), limit); + limit = NS_MIN(limit, static_cast(step)); + PRUint32 bytesToRead = static_cast(limit); + PRUint32 bytesRead = 0; + char* buffer = ogg_sync_buffer(&mOggState, + bytesToRead); + NS_ASSERTION(buffer, "Must have buffer"); + stream->Read(buffer, bytesToRead, &bytesRead); + + // Update the synchronisation layer with the number + // of bytes written to the buffer + ret = ogg_sync_wrote(&mOggState, bytesRead); + if (ret != 0) { + endTime = -1; + break; + } + + continue; + } + + if (ret < 0 || ogg_page_granulepos(&page) < 0) { + continue; + } + + PRUint32 checksum = GetChecksum(&page); + if (checksumAfterSeek == 0) { + // This is the first page we've decoded after a backoff/seek. Remember + // the page checksum. If we backoff further and encounter this page + // again, we'll know that we won't find a page with an end time after + // this one, so we'll know to back off again. + checksumAfterSeek = checksum; + } + if (checksum == prevChecksumAfterSeek) { + // This page has the same checksum as the first page we encountered + // after the last backoff/seek. Since we've already scanned after this + // page and failed to find an end time, we may as well backoff again and + // try to find an end time from an earlier page. + mustBackOff = PR_TRUE; + continue; + } + + PRInt64 granulepos = ogg_page_granulepos(&page); + int serial = ogg_page_serialno(&page); + + nsOggCodecState* codecState = nsnull; + mCodecStates.Get(serial, &codecState); + + if (!codecState) { + // This page is from a bitstream which we haven't encountered yet. + // It's probably from a new "link" in a "chained" ogg. Don't + // bother even trying to find a duration... + break; + } + + PRInt64 t = codecState ? codecState->Time(granulepos) : -1; + if (t != -1) { + endTime = t; + } + } + + ogg_sync_reset(&mOggState); + + return endTime; +} diff --git a/content/media/ogg/nsOggReader.h b/content/media/ogg/nsOggReader.h new file mode 100644 index 000000000000..4ee945c49d69 --- /dev/null +++ b/content/media/ogg/nsOggReader.h @@ -0,0 +1,531 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 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 code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ +#if !defined(nsOggReader_h_) +#define nsOggReader_h_ + +#include +#include "nsOggCodecState.h" +#include +#include +#include +#include "prmon.h" +#include "nsAutoLock.h" +#include "nsClassHashtable.h" +#include "mozilla/TimeStamp.h" +#include "nsSize.h" +#include "nsRect.h" +#include "mozilla/Monitor.h" + +class nsOggPlayStateMachine; + +using mozilla::Monitor; +using mozilla::MonitorAutoEnter; +using mozilla::TimeDuration; +using mozilla::TimeStamp; + +// Holds chunk a decoded sound samples. +class SoundData { +public: + SoundData(PRInt64 aTime, + PRInt64 aDuration, + PRUint32 aSamples, + float* aData, + PRUint32 aChannels) + : mTime(aTime), + mDuration(aDuration), + mSamples(aSamples), + mAudioData(aData), + mChannels(aChannels) + { + MOZ_COUNT_CTOR(SoundData); + } + + SoundData(PRInt64 aDuration, + PRUint32 aSamples, + float* aData, + PRUint32 aChannels) + : mTime(-1), + mDuration(aDuration), + mSamples(aSamples), + mAudioData(aData), + mChannels(aChannels) + { + MOZ_COUNT_CTOR(SoundData); + } + + ~SoundData() + { + MOZ_COUNT_DTOR(SoundData); + } + + PRUint32 AudioDataLength() { + return mChannels * mSamples; + } + + PRInt64 mTime; // Start time of samples in ms. + const PRInt64 mDuration; // In ms. + const PRUint32 mSamples; + const PRUint32 mChannels; + nsAutoArrayPtr mAudioData; +}; + +// Holds a decoded Theora frame, in YCbCr format. These are queued in the reader. +class VideoData { +public: + + // Constructs a VideoData object. Makes a copy of YCbCr data in aBuffer. + // This may return nsnull if we run out of memory when allocating buffers + // to store the frame. + static VideoData* Create(PRInt64 aTime, + th_ycbcr_buffer aBuffer, + PRBool aKeyframe, + PRInt64 aGranulepos); + + // Constructs a duplicate VideoData object. This intrinsically tells the + // player that it does not need to update the displayed frame when this + // frame is played; this frame is identical to the previous. + static VideoData* CreateDuplicate(PRInt64 aTime, + PRInt64 aGranulepos) + { + return new VideoData(aTime, aGranulepos); + } + + ~VideoData() + { + MOZ_COUNT_DTOR(VideoData); + for (PRUint32 i = 0; i < 3; ++i) { + delete mBuffer[i].data; + } + } + + // Start time of frame in milliseconds. + PRInt64 mTime; + PRInt64 mGranulepos; + + th_ycbcr_buffer mBuffer; + + // When PR_TRUE, denotes that this frame is identical to the frame that + // came before; it's a duplicate. mBuffer will be empty. + PRPackedBool mDuplicate; + PRPackedBool mKeyframe; + +private: + VideoData(PRInt64 aTime, PRInt64 aGranulepos) : + mTime(aTime), + mGranulepos(aGranulepos), + mDuplicate(PR_TRUE), + mKeyframe(PR_FALSE) + { + MOZ_COUNT_CTOR(VideoData); + memset(&mBuffer, 0, sizeof(th_ycbcr_buffer)); + } + + VideoData(PRInt64 aTime, + PRBool aKeyframe, + PRInt64 aGranulepos) + : mTime(aTime), + mGranulepos(aGranulepos), + mDuplicate(PR_FALSE), + mKeyframe(aKeyframe) + { + MOZ_COUNT_CTOR(VideoData); + } + +}; + +// Thread and type safe wrapper around nsDeque. +template +class MediaQueueDeallocator : public nsDequeFunctor { + virtual void* operator() (void* anObject) { + delete static_cast(anObject); + return nsnull; + } +}; + +template class MediaQueue : private nsDeque { + public: + + MediaQueue() + : nsDeque(new MediaQueueDeallocator()), + mMonitor("mediaqueue"), + mEndOfStream(0) + {} + + ~MediaQueue() { + Reset(); + } + + inline PRInt32 GetSize() { + MonitorAutoEnter mon(mMonitor); + return nsDeque::GetSize(); + } + + inline void Push(T* aItem) { + MonitorAutoEnter mon(mMonitor); + nsDeque::Push(aItem); + } + + inline void PushFront(T* aItem) { + MonitorAutoEnter mon(mMonitor); + nsDeque::PushFront(aItem); + } + + inline T* Pop() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::Pop()); + } + + inline T* PopFront() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::PopFront()); + } + + inline T* Peek() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::Peek()); + } + + inline T* PeekFront() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::PeekFront()); + } + + inline void Empty() { + MonitorAutoEnter mon(mMonitor); + nsDeque::Empty(); + } + + inline void Erase() { + MonitorAutoEnter mon(mMonitor); + nsDeque::Erase(); + } + + void Reset() { + MonitorAutoEnter mon(mMonitor); + while (GetSize() > 0) { + T* x = PopFront(); + delete x; + } + mEndOfStream = PR_FALSE; + } + + PRBool AtEndOfStream() { + MonitorAutoEnter mon(mMonitor); + return GetSize() == 0 && mEndOfStream; + } + + void Finish() { + MonitorAutoEnter mon(mMonitor); + mEndOfStream = PR_TRUE; + } + + // Returns the approximate number of milliseconds of samples in the queue. + PRInt64 Duration() { + MonitorAutoEnter mon(mMonitor); + if (GetSize() < 2) { + return 0; + } + T* last = Peek(); + T* first = PeekFront(); + return last->mTime - first->mTime; + } + +private: + Monitor mMonitor; + + // PR_TRUE when we've decoded the last packet in the bitstream for which + // we're queueing sample-data. + PRBool mEndOfStream; +}; + +// Represents a section of contiguous media, with a start and end offset, +// and the timestamps of the start and end of that range. Used to denote the +// extremities of a range to seek in. +class ByteRange { +public: + ByteRange() : + mOffsetStart(0), + mOffsetEnd(0), + mTimeStart(0), + mTimeEnd(0) + {} + + ByteRange(PRInt64 aOffsetStart, + PRInt64 aOffsetEnd, + PRInt64 aTimeStart, + PRInt64 aTimeEnd) + : mOffsetStart(aOffsetStart), + mOffsetEnd(aOffsetEnd), + mTimeStart(aTimeStart), + mTimeEnd(aTimeEnd) + {} + + PRBool IsNull() { + return mOffsetStart == 0 && + mOffsetEnd == 0 && + mTimeStart == 0 && + mTimeEnd == 0; + } + + PRInt64 mOffsetStart, mOffsetEnd; // in bytes. + PRInt64 mTimeStart, mTimeEnd; // in ms. +}; + +// Stores info relevant to presenting media samples. +class nsOggInfo { +public: + nsOggInfo() + : mFramerate(0.0), + mAspectRatio(1.0), + mCallbackPeriod(1), + mAudioRate(0), + mAudioChannels(0), + mFrame(0,0), + mHasAudio(PR_FALSE), + mHasVideo(PR_FALSE) + {} + + // Frames per second. + float mFramerate; + + // Aspect ratio, as stored in the video header packet. + float mAspectRatio; + + // Length of a video frame in milliseconds, or the callback period if + // there's no audio. + PRUint32 mCallbackPeriod; + + // Samples per second. + PRUint32 mAudioRate; + + // Number of audio channels. + PRUint32 mAudioChannels; + + // Dimensions of the video frame. + nsIntSize mFrame; + + // The picture region inside the video frame to be displayed. + nsIntRect mPicture; + + // The offset of the first non-header page in the file, in bytes. + // Used to seek to the start of the media. + PRInt64 mDataOffset; + + // PR_TRUE if we have an active audio bitstream. + PRPackedBool mHasAudio; + + // PR_TRUE if we have an active video bitstream. + PRPackedBool mHasVideo; +}; + +// Encapsulates the decoding and reading of Ogg data. Reading can be done +// on either the state machine thread (when loading and seeking) or on +// the reader thread (when it's reading and decoding). The reader encapsulates +// the reading state and maintains it's own monitor to ensure thread safety +// and correctness. Never hold the nsOggDecoder's monitor when calling into +// this class. +class nsOggReader : public nsRunnable { +public: + nsOggReader(nsOggPlayStateMachine* aStateMachine); + ~nsOggReader(); + + PRBool HasAudio() + { + MonitorAutoEnter mon(mMonitor); + return mVorbisState != 0 && mVorbisState->mActive; + } + + PRBool HasVideo() + { + MonitorAutoEnter mon(mMonitor); + return mTheoraState != 0 && mTheoraState->mActive; + } + + // Read header data for all bitstreams in the Ogg file. Fills aInfo with + // the data required to present the media. Returns NS_OK on success, + // or NS_ERROR_FAILURE on failure. + nsresult ReadOggHeaders(nsOggInfo& aInfo); + + // Stores the presentation time of the first sample in the stream in + // aOutStartTime, and returns the first video sample, if we have video. + VideoData* FindStartTime(PRInt64 aOffset, + PRInt64& aOutStartTime); + + // Returns the end time of the last page which occurs before aEndOffset. + // This will not read past aEndOffset. Returns -1 on failure. + PRInt64 FindEndTime(PRInt64 aEndOffset); + + // Decodes one Vorbis page, enqueuing the audio data in mAudioQueue. + // Returns PR_TRUE when there's more audio to decode, PR_FALSE if the + // audio is finished, end of file has been reached, or an un-recoverable + // read error has occured. + PRBool DecodeAudioPage(); + + // Reads and decodes one video frame. If the Theora granulepos has not + // been captured, it may read several packets until one with a granulepos + // has been captured, to ensure that all packets read have valid time info. + // Packets with a timestamp less than aTimeThreshold will be decoded (unless + // they're not keyframes and aKeyframeSkip is PR_TRUE), but will not be + // added to the queue. + PRBool DecodeVideoPage(PRBool &aKeyframeSkip, + PRInt64 aTimeThreshold); + + // Moves the decode head to aTime milliseconds. aStartTime and aEndTime + // denote the start and end times of the media. + nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime); + + // Queue of audio samples. This queue is threadsafe. + MediaQueue mAudioQueue; + + // Queue of video samples. This queue is threadsafe. + MediaQueue mVideoQueue; + + // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE + // on failure. + nsresult Init(); + +private: + + // Ogg reader decode function. Matches DecodeVideoPage() and + // DecodeAudioPage(). + typedef PRBool (nsOggReader::*DecodeFn)(); + + // Calls aDecodeFn on *this until aQueue has a sample, whereupon + // we return the first sample. + template + Data* DecodeToFirstData(DecodeFn aDecodeFn, + MediaQueue& aQueue); + + // Wrapper so that DecodeVideoPage(PRBool&,PRInt64) can be called from + // DecodeToFirstData(). + PRBool DecodeVideoPage() { + PRBool f = PR_FALSE; + return DecodeVideoPage(f, 0); + } + + // Decodes one packet of Vorbis data, storing the resulting chunks of + // PCM samples in aChunks. + nsresult DecodeVorbis(nsTArray& aChunks, + ogg_packet* aPacket); + + // May return NS_ERROR_OUT_OF_MEMORY. + nsresult DecodeTheora(nsTArray& aFrames, + ogg_packet* aPacket); + + // Resets all state related to decoding, emptying all buffers etc. + nsresult ResetDecode(); + + // Read a page of data from the Ogg file. Returns the offset of the start + // of the page, or -1 if the page read failed. + PRInt64 ReadOggPage(ogg_page* aPage); + + // Read a packet for an Ogg bitstream/codec state. Returns PR_TRUE on + // success, or PR_FALSE if the read failed. + PRBool ReadOggPacket(nsOggCodecState* aCodecState, ogg_packet* aPacket); + + // Performs a seek bisection to move the media stream's read cursor to the + // last ogg page boundary which has end time before aTarget ms on both the + // Theora and Vorbis bitstreams. Limits its search to data inside aRange; + // i.e. it will only read inside of the aRange's start and end offsets. + // aFuzz is the number of ms of leniency we'll allow; we'll terminate the + // seek when we land in the range (aTime - aFuzz, aTime) ms. + nsresult SeekBisection(PRInt64 aTarget, + const ByteRange& aRange, + PRUint32 aFuzz); + + // Fills aRanges with ByteRanges denoting the sections of the media which + // have been downloaded and are stored in the media cache. The reader + // monitor must must be held with exactly one lock count. The nsMediaStream + // must be pinned while calling this. + nsresult GetBufferedBytes(nsTArray& aRanges); + + // Returns the range in which you should perform a seek bisection if + // you wish to seek to aTarget ms, given the known (buffered) byte ranges + // in aRanges. If aExact is PR_TRUE, we only return an exact copy of a + // range in which aTarget lies, or a null range if aTarget isn't contained + // in any of the (buffered) ranges. Otherwise, when aExact is PR_FALSE, + // we'll construct the smallest possible range we can, based on the times + // and byte offsets known in aRanges. We can then use this to minimize our + // bisection's search space when the target isn't in a known buffered range. + ByteRange GetSeekRange(const nsTArray& aRanges, + PRInt64 aTarget, + PRInt64 aStartTime, + PRInt64 aEndTime, + PRBool aExact); + + // The lock which we hold whenever we read or decode. This ensures the thread + // safety of the reader and its data fields. + Monitor mMonitor; + + // Reference to the owning player state machine object. Do not hold the + // reader's monitor when accessing the player. + nsOggPlayStateMachine* mPlayer; + + // Maps Ogg serialnos to nsOggStreams. + nsClassHashtable mCodecStates; + + // Decode state of the Theora bitstream we're decoding, if we have video. + nsTheoraState* mTheoraState; + + // Decode state of the Vorbis bitstream we're decoding, if we have audio. + nsVorbisState* mVorbisState; + + // Ogg decoding state. + ogg_sync_state mOggState; + + // The offset of the end of the last page we've read, or the start of + // the page we're about to read. + PRInt64 mPageOffset; + + // The offset of the start of the first non-header page in the file. + // Used to seek to media start time. + PRInt64 mDataOffset; + + // The granulepos of the last decoded Theora frame. + PRInt64 mTheoraGranulepos; + + // The granulepos of the last decoded Vorbis sample. + PRInt64 mVorbisGranulepos; + + // Number of milliseconds of data video/audio data held in a frame. + PRUint32 mCallbackPeriod; + +}; + +#endif diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index 04f9bf719eb8..6b8731af637c 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -104,6 +104,7 @@ _TEST_FILES = \ test_playback_errors.html \ test_reactivate.html \ test_readyState.html \ + test_seek.html \ test_seek2.html \ test_volume.html \ use_large_cache.js \ @@ -113,23 +114,17 @@ _TEST_FILES = \ # test_resume.html \ # -ifneq ($(OS_ARCH),WINNT) -# These tests are disabled on windows until we -# figure out the random failures. See bug 475369. -_TEST_FILES += \ - test_seek.html \ - $(NULL) -endif - # Ogg sample files _TEST_FILES += \ 320x240.ogv \ 320x240.allow-origin.ogv \ 320x240.allow-origin.ogv^headers^ \ 448636.ogv \ + audio-overhang.ogg \ beta-phrasebook.ogg \ bogus.ogv \ bug495129.ogv \ + bug495794.ogg \ bug461281.ogg \ bug482461.ogv \ bug498380.ogv \ @@ -157,6 +152,7 @@ _TEST_FILES += \ short-video.ogv \ small-shot.ogg \ sound.ogg \ + video-overhang.ogg \ $(NULL) # Wave sample files diff --git a/content/media/test/audio-overhang.ogg b/content/media/test/audio-overhang.ogg new file mode 100644 index 000000000000..c07986e7a1c6 Binary files /dev/null and b/content/media/test/audio-overhang.ogg differ diff --git a/content/media/test/bug495794.ogg b/content/media/test/bug495794.ogg new file mode 100644 index 000000000000..1c19a640612d Binary files /dev/null and b/content/media/test/bug495794.ogg differ diff --git a/content/media/test/manifest.js b/content/media/test/manifest.js index b2008c1cf81c..4e30d5b20dfc 100644 --- a/content/media/test/manifest.js +++ b/content/media/test/manifest.js @@ -40,7 +40,7 @@ var gPlayTests = [ // Ogg stream with eof marker { name:"bug461281.ogg", type:"application/ogg" }, // oggz-chop stream - { name:"bug482461.ogv", type:"video/ogg", duration:4.24 }, + { name:"bug482461.ogv", type:"video/ogg", duration:4.34 }, // With first frame a "duplicate" (empty) frame. { name:"bug500311.ogv", type:"video/ogg", duration:1.96 }, // Small audio file @@ -50,9 +50,10 @@ var gPlayTests = [ // First Theora data packet is zero bytes. { name:"bug504613.ogv", type:"video/ogg" }, // Multiple audio streams. - { name:"bug516323.ogv", type:"video/ogg", duration:4.424 }, + { name:"bug516323.ogv", type:"video/ogg", duration:4.208 }, + // Encoded with vorbis beta1, includes unusually sized codebooks - { name:"beta-phrasebook.ogg", type:"audio/ogg", duration:4 }, + { name:"beta-phrasebook.ogg", type:"audio/ogg", duration:4.01 }, // Small file, only 1 frame with audio only. { name:"bug520493.ogg", type:"audio/ogg", duration:0.458 }, // Small file with vorbis comments with 0 length values and names. @@ -61,13 +62,17 @@ var gPlayTests = [ // Various weirdly formed Ogg files { name:"bug499519.ogv", type:"video/ogg", duration:0.24 }, { name:"bug506094.ogv", type:"video/ogg", duration:0 }, - { name:"bug501279.ogg", type:"audio/ogg", duration:0 }, - { name:"bug498855-1.ogv", type:"video/ogg", duration:0.2 }, - { name:"bug498855-2.ogv", type:"video/ogg", duration:0.2 }, - { name:"bug498855-3.ogv", type:"video/ogg", duration:0.2 }, - { name:"bug504644.ogv", type:"video/ogg", duration:1.56 }, + { name:"bug498855-1.ogv", type:"video/ogg", duration:0.24 }, + { name:"bug498855-2.ogv", type:"video/ogg", duration:0.24 }, + { name:"bug498855-3.ogv", type:"video/ogg", duration:0.24 }, + { name:"bug504644.ogv", type:"video/ogg", duration:1.6 }, { name:"chain.ogv", type:"video/ogg", duration:Number.NaN }, - { name:"bug523816.ogv", type:"video/ogg", duration:0.5 }, + { name:"bug523816.ogv", type:"video/ogg", duration:0.533 }, + { name:"bug495129.ogv", type:"video/ogg", duration:2.41 }, + { name:"bug498380.ogv", type:"video/ogg" }, + { name:"bug495794.ogg", type:"audio/ogg", duration:0.3}, + { name:"audio-overhang.ogg", type:"audio/ogg", duration:2.3}, + { name:"video-overhang.ogg", type:"audio/ogg", duration:3.966}, { name:"bogus.duh", type:"bogus/duh" } ]; @@ -82,9 +87,8 @@ var gErrorTests = [ { name:"bogus.wav", type:"audio/x-wav" }, { name:"bogus.ogv", type:"video/ogg" }, { name:"448636.ogv", type:"video/ogg" }, - { name:"bug495129.ogv", type:"video/ogg", duration:2.52 }, - { name:"bug504843.ogv", type:"video/ogg", duration:1.233 }, - { name:"bug498380.ogv", type:"video/ogg" }, + { name:"bug504843.ogv", type:"video/ogg" }, + { name:"bug501279.ogg", type:"audio/ogg" }, { name:"bogus.duh", type:"bogus/duh" } ]; diff --git a/content/media/test/test_duration1.html b/content/media/test/test_duration1.html index f6417782c569..ef2669b5d321 100644 --- a/content/media/test/test_duration1.html +++ b/content/media/test/test_duration1.html @@ -17,7 +17,7 @@ function startTest() { if (completed) return false; var v = document.getElementById('v'); - is(Math.round(v.duration*1000), 3966, "Check duration of video: " + v.duration); + is(Math.round(v.duration*1000), 3999, "Check duration of video: " + v.duration); completed = true; clearTimeout(timeout); SimpleTest.finish(); diff --git a/content/media/test/test_info_leak.html b/content/media/test/test_info_leak.html index 0f24ae376e5d..98f9988a28da 100644 --- a/content/media/test/test_info_leak.html +++ b/content/media/test/test_info_leak.html @@ -158,7 +158,7 @@ function checkState() { "Ready state of " + gMedia.readyState + " was leaked"); test_is(gMedia.seeking, false, "Seeking leaked"); test_is(gMedia.currentTime, 0, "Leaked currentTime"); - test_is(gMedia.duration, 0, "Leaked duration"); + test_ok(isNaN(gMedia.duration), "Leaked duration"); test_is(gMedia.paused, true, "Paused leaked"); test_is(gMedia.ended, false, "Ended leaked"); test_is(gMedia.autoplay, false, "Autoplay leaked"); diff --git a/content/media/test/test_playback.html b/content/media/test/test_playback.html index 33be3e1c1525..fc261be16802 100644 --- a/content/media/test/test_playback.html +++ b/content/media/test/test_playback.html @@ -30,7 +30,9 @@ function startTests() { continue; v.src = test.name; + v.name = test.name; var check = function(test, v) { return function() { + is(test.name, v.name, "Name should match test.name #1"); checkMetadata(test.name, v, test); }}(test, v); var noLoad = function(test, v) { return function() { @@ -39,8 +41,9 @@ function startTests() { var checkEnded = function(test, v) { return function() { if (test.duration) { ok(Math.abs(v.currentTime - test.duration) < 0.1, - test.name + " current time at end: " + v.currentTime); + test.name + " current time at end: " + v.currentTime + " should be: " + test.duration); } + is(test.name, v.name, "Name should match test.name #2"); is(v.readyState, v.HAVE_CURRENT_DATA, test.name + " checking readyState"); ok(v.readyState != v.NETWORK_LOADED, test.name + " shouldn't report NETWORK_LOADED"); ok(v.ended, test.name + " checking playback has ended"); @@ -50,6 +53,7 @@ function startTests() { } }}(test, v); var checkSuspended = function(test, v) { return function() { + is(test.name, v.name, "Name should match test.name #3"); if (v.seenSuspend) return; @@ -61,12 +65,13 @@ function startTests() { } }}(test, v); v.prevTime = 0; - var timeUpdate = function(v) { return function() { + var timeUpdate = function(test, v) { return function() { + is(test.name, v.name, "Name should match test.name #4"); ok(v.prevTime <= v.currentTime, test.name + " time should run forwards: p=" + v.prevTime + " c=" + v.currentTime); v.prevTime = v.currentTime; - }}(v); + }}(test, v); v.addEventListener("load", noLoad, false); v.addEventListener("loadedmetadata", check, false); v.addEventListener("timeupdate", timeUpdate, false); diff --git a/content/media/test/test_timeupdate1.html b/content/media/test/test_timeupdate1.html index 3a747a3bb294..4dc566744e87 100644 --- a/content/media/test/test_timeupdate1.html +++ b/content/media/test/test_timeupdate1.html @@ -29,10 +29,8 @@ function timeUpdated() { var v = document.getElementById('v'); ok(v.currentTime > lastTime, - "Check currentTime of " + - v.currentTime + - " is greater than last time of " + - lastTime); + "currentTime (" + v.currentTime + + ") should be greater than last time (" + lastTime + ")"); lastTime = v.currentTime; return false; } diff --git a/content/media/test/video-overhang.ogg b/content/media/test/video-overhang.ogg new file mode 100644 index 000000000000..e11b28fb5bbc Binary files /dev/null and b/content/media/test/video-overhang.ogg differ diff --git a/content/media/wave/nsWaveDecoder.cpp b/content/media/wave/nsWaveDecoder.cpp index 6818368a6b79..511edca5c6cc 100644 --- a/content/media/wave/nsWaveDecoder.cpp +++ b/content/media/wave/nsWaveDecoder.cpp @@ -648,7 +648,7 @@ nsWaveStateMachine::Run() PRUint32 lengthInSamples = got / sampleSize; monitor.Exit(); - mAudioStream->Write(buf.get(), lengthInSamples); + mAudioStream->Write(buf.get(), lengthInSamples, PR_FALSE); monitor.Enter(); FirePositionChanged(PR_FALSE); diff --git a/content/smil/nsSMILInstanceTime.h b/content/smil/nsSMILInstanceTime.h index 6b05ace864d6..b76e87641720 100644 --- a/content/smil/nsSMILInstanceTime.h +++ b/content/smil/nsSMILInstanceTime.h @@ -124,36 +124,7 @@ public: PRUint32 Serial() const { return mSerial; } void SetSerial(PRUint32 aIndex) { mSerial = aIndex; } - nsrefcnt AddRef() - { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); - return mRefCnt; - } - NS_ASSERT_OWNINGTHREAD(_class); - NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), - "nsSMILInstanceTime addref isn't thread-safe!"); - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsSMILInstanceTime", sizeof(*this)); - return mRefCnt; - } - - nsrefcnt Release() - { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); - return mRefCnt; - } - NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), - "nsSMILInstanceTime release isn't thread-safe!"); - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsSMILInstanceTime"); - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsSMILInstanceTime) protected: void SetBaseInterval(nsSMILInterval* aBaseInterval); @@ -162,9 +133,6 @@ protected: nsSMILTimeValue mTime; - nsAutoRefCnt mRefCnt; - NS_DECL_OWNINGTHREAD - // Internal flags used for represent behaviour of different instance times` enum { // Indicates if this instance time should be removed when the owning timed diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index 6aca93d9b948..b0a68971af21 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -1132,7 +1132,7 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName, nsCSSProps::LookupProperty(nsAtomString(aMappedAttrName)); PRBool changed; // outparam for ParseProperty. (ignored) mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI, - mNodePrincipal, mDecl, &changed); + mNodePrincipal, mDecl, &changed, PR_FALSE); } already_AddRefed diff --git a/content/svg/content/src/nsSVGMatrix.cpp b/content/svg/content/src/nsSVGMatrix.cpp index ee155e5aa7ac..c7e7d75612d1 100644 --- a/content/svg/content/src/nsSVGMatrix.cpp +++ b/content/svg/content/src/nsSVGMatrix.cpp @@ -41,6 +41,7 @@ #include "nsSVGValue.h" #include #include "nsContentUtils.h" +#include "nsISupportsImpl.h" const double radPerDegree = 2.0*3.1415926535 / 360.0; diff --git a/content/svg/content/src/nsSVGMatrix.h b/content/svg/content/src/nsSVGMatrix.h index 6d1f5d2f2612..c95002031716 100644 --- a/content/svg/content/src/nsSVGMatrix.h +++ b/content/svg/content/src/nsSVGMatrix.h @@ -71,6 +71,7 @@ #include "nsIDOMSVGMatrix.h" #include "gfxMatrix.h" +#include "nsAutoPtr.h" nsresult NS_NewSVGMatrix(nsIDOMSVGMatrix** result, diff --git a/content/xbl/crashtests/crashtests.list b/content/xbl/crashtests/crashtests.list index 69894e24d02e..1a63e3d16b7c 100644 --- a/content/xbl/crashtests/crashtests.list +++ b/content/xbl/crashtests/crashtests.list @@ -24,6 +24,7 @@ load 415192-1.xul load 420233-1.xhtml load 421997-1.xhtml load 432813-1.xhtml +load 454820-1.html load 460665-1.xhtml load 464863-1.xhtml load 472260-1.xhtml diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index 492c9757ee5d..d88633a70899 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -46,6 +46,7 @@ #include "nsClassHashtable.h" #include "nsTArray.h" #include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" class nsXBLPrototypeBinding; class nsIContent; @@ -77,24 +78,7 @@ public: * which are queued to fire their constructors. */ - nsrefcnt AddRef() - { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLBinding", sizeof(nsXBLBinding)); - return mRefCnt; - } - - nsrefcnt Release() - { - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLBinding"); - if (mRefCnt == 0) { - mRefCnt = 1; - delete this; - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsXBLBinding) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding) @@ -172,7 +156,6 @@ public: // MEMBER VARIABLES protected: - nsAutoRefCnt mRefCnt; nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. nsRefPtr mNextBinding; // Strong. The derived binding owns the base class bindings. diff --git a/content/xbl/src/nsXBLInsertionPoint.cpp b/content/xbl/src/nsXBLInsertionPoint.cpp index 62e703195086..d3d0dc582fa8 100644 --- a/content/xbl/src/nsXBLInsertionPoint.cpp +++ b/content/xbl/src/nsXBLInsertionPoint.cpp @@ -57,19 +57,6 @@ nsXBLInsertionPoint::~nsXBLInsertionPoint() } } -nsrefcnt -nsXBLInsertionPoint::Release() -{ - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPoint"); - if (mRefCnt == 0) { - mRefCnt = 1; - delete this; - return 0; - } - return mRefCnt; -} - NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) diff --git a/content/xbl/src/nsXBLInsertionPoint.h b/content/xbl/src/nsXBLInsertionPoint.h index c1f05045a4df..5ec9239bd3f3 100644 --- a/content/xbl/src/nsXBLInsertionPoint.h +++ b/content/xbl/src/nsXBLInsertionPoint.h @@ -50,15 +50,7 @@ public: nsXBLInsertionPoint(nsIContent* aParentElement, PRUint32 aIndex, nsIContent* aDefContent); ~nsXBLInsertionPoint(); - nsrefcnt AddRef() - { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPoint", - sizeof(nsXBLInsertionPoint)); - return mRefCnt; - } - - nsrefcnt Release(); + NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPoint) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint) @@ -90,7 +82,6 @@ public: void UnbindDefaultContent(); protected: - nsAutoRefCnt mRefCnt; nsIContent* mParentElement; // This ref is weak. The parent of the element. PRInt32 mIndex; // The index of this insertion point. -1 is a pseudo-point. nsCOMArray mElements; // An array of elements present at the insertion point. diff --git a/content/xbl/src/nsXBLPrototypeBinding.cpp b/content/xbl/src/nsXBLPrototypeBinding.cpp index 8b6e97d2b036..4f417c8e1c60 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -207,27 +207,12 @@ public: nsXBLInsertionPointEntry::ReleasePool(); } - nsrefcnt AddRef() { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPointEntry", sizeof(nsXBLInsertionPointEntry)); - return mRefCnt; - } - - nsrefcnt Release() { - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPointEntry"); - if (mRefCnt == 0) { - Destroy(this); - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPointEntry) protected: nsCOMPtr mInsertionParent; nsCOMPtr mDefaultContent; PRUint32 mInsertionIndex; - nsAutoRefCnt mRefCnt; nsXBLInsertionPointEntry(nsIContent* aParent) : mInsertionParent(aParent), diff --git a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp index daf934456161..2ab7c3f11795 100644 --- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp @@ -404,14 +404,12 @@ public: txCompileObserver(txMozillaXSLTProcessor* aProcessor, nsILoadGroup* aLoadGroup); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txCompileObserver) nsresult startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsIPrincipal* aSourcePrincipal); -protected: - nsAutoRefCnt mRefCnt; - private: nsRefPtr mProcessor; nsCOMPtr mLoadGroup; @@ -429,23 +427,6 @@ txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor, { } -nsrefcnt -txCompileObserver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txCompileObserver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - nsresult txCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -658,11 +639,11 @@ class txSyncCompileObserver : public txACompileObserver public: txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver) protected: nsRefPtr mProcessor; - nsAutoRefCnt mRefCnt; }; txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) @@ -670,23 +651,6 @@ txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) { } -nsrefcnt -txSyncCompileObserver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txSyncCompileObserver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - nsresult txSyncCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, diff --git a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp index 11347fbbfd06..f68ad544ccad 100644 --- a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp @@ -64,7 +64,8 @@ class txDriver : public txACompileObserver const XML_Char *aSystemId, const XML_Char *aPublicId); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txDriver) nsRefPtr mCompiler; protected: @@ -73,7 +74,6 @@ class txDriver : public txACompileObserver // keep track of the nsresult returned by the handlers, expat forgets them nsresult mRV; XML_Parser mExpatParser; - nsAutoRefCnt mRefCnt; }; nsresult @@ -338,23 +338,6 @@ txDriver::createErrorString() * txACompileObserver implementation */ -nsrefcnt -txDriver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txDriver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - void txDriver::onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, const PRUnichar *aErrorText, const PRUnichar *aParam) diff --git a/content/xslt/src/xslt/txStylesheet.h b/content/xslt/src/xslt/txStylesheet.h index 5f6228f1fbe9..cd159e8f7306 100644 --- a/content/xslt/src/xslt/txStylesheet.h +++ b/content/xslt/src/xslt/txStylesheet.h @@ -44,6 +44,7 @@ #include "txList.h" #include "txXSLTPatterns.h" #include "nsTPtrArray.h" +#include "nsISupportsImpl.h" class txInstruction; class txToplevelItem; @@ -67,20 +68,8 @@ public: txStylesheet(); ~txStylesheet(); nsresult init(); - - nsrefcnt AddRef() - { - return ++mRefCnt; - } - nsrefcnt Release() - { - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; - } + + NS_INLINE_DECL_REFCOUNTING(txStylesheet) txInstruction* findTemplate(const txXPathNode& aNode, const txExpandedName& aMode, @@ -159,9 +148,6 @@ private: nsTPtrArray& aFrameStripSpaceTests); nsresult addAttributeSet(txAttributeSetItem* aAttributeSetItem); - // Refcount - nsAutoRefCnt mRefCnt; - // List of ImportFrames txList mImportFrames; diff --git a/content/xslt/src/xslt/txStylesheetCompiler.cpp b/content/xslt/src/xslt/txStylesheetCompiler.cpp index 759c5cb4306d..d0050683fd0b 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStylesheetCompiler.cpp @@ -69,27 +69,6 @@ txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI, mStatus = init(aStylesheetURI, aStylesheet, aInsertPosition); } -nsrefcnt -txStylesheetCompiler::AddRef() -{ - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "txStylesheetCompiler", sizeof(*this)); - return mRefCnt; -} - -nsrefcnt -txStylesheetCompiler::Release() -{ - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "txStylesheetCompiler"); - if (mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - void txStylesheetCompiler::setBaseURI(const nsString& aBaseURI) { diff --git a/content/xslt/src/xslt/txStylesheetCompiler.h b/content/xslt/src/xslt/txStylesheetCompiler.h index fc23fb4d3d89..4d71484af266 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.h +++ b/content/xslt/src/xslt/txStylesheetCompiler.h @@ -77,8 +77,8 @@ public: class txACompileObserver { public: - virtual nsrefcnt AddRef() = 0; - virtual nsrefcnt Release() = 0; + virtual void AddRef() = 0; + virtual void Release() = 0; virtual nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -90,13 +90,11 @@ public: }; #define TX_DECL_ACOMPILEOBSERVER \ - nsrefcnt AddRef(); \ - nsrefcnt Release(); \ nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, \ txStylesheetCompiler* aCompiler); \ void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, \ const PRUnichar *aErrorText = nsnull, \ - const PRUnichar *aParam = nsnull) + const PRUnichar *aParam = nsnull); class txStylesheetCompilerState : public txIParseContext { @@ -215,8 +213,6 @@ public: txStylesheet* aStylesheet, txListIterator* aInsertPosition, txACompileObserver* aObserver); - virtual nsrefcnt AddRef(); - virtual nsrefcnt Release(); void setBaseURI(const nsString& aBaseURI); @@ -235,12 +231,8 @@ public: txStylesheet* getStylesheet(); - // txACompileObserver - nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, - txStylesheetCompiler* aCompiler); - void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, - const PRUnichar *aErrorText = nsnull, - const PRUnichar *aParam = nsnull); + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txStylesheetCompiler) private: nsresult startElementInternal(PRInt32 aNamespaceID, nsIAtom* aLocalName, @@ -253,7 +245,6 @@ private: nsresult ensureNewElementContext(); nsresult maybeDoneCompiling(); - nsAutoRefCnt mRefCnt; nsString mCharacters; nsresult mStatus; }; diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 914001b3826f..ad208e62a434 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -4164,8 +4164,6 @@ nsXULDocument::BroadcasterHookup::~BroadcasterHookup() #ifdef PR_LOGGING if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING) && !mResolved) { // Tell the world we failed - nsresult rv; - nsIAtom *tag = mObservesElement->Tag(); nsAutoString broadcasterID; diff --git a/content/xul/templates/src/nsRDFBinding.h b/content/xul/templates/src/nsRDFBinding.h index 2a8ab79973fc..82ad20068ddf 100644 --- a/content/xul/templates/src/nsRDFBinding.h +++ b/content/xul/templates/src/nsRDFBinding.h @@ -40,6 +40,7 @@ #include "nsAutoPtr.h" #include "nsIAtom.h" #include "nsIRDFResource.h" +#include "nsISupportsImpl.h" class nsXULTemplateResultRDF; class nsBindingValues; @@ -95,9 +96,6 @@ class RDFBindingSet { protected: - // results hold a reference to a binding set in their nsBindingValues fields - PRInt32 mRefCnt; - // the number of bindings PRInt32 mCount; @@ -107,8 +105,7 @@ protected: public: RDFBindingSet() - : mRefCnt(0), - mCount(0), + : mCount(0), mFirst(nsnull) { MOZ_COUNT_CTOR(RDFBindingSet); @@ -116,19 +113,7 @@ public: ~RDFBindingSet(); - PRInt32 AddRef() { - mRefCnt++; - NS_LOG_ADDREF(this, mRefCnt, "RDFBindingSet", sizeof(*this)); - return mRefCnt; - } - - PRInt32 Release() - { - PRInt32 refcnt = --mRefCnt; - NS_LOG_RELEASE(this, refcnt, "RDFBindingSet"); - if (refcnt == 0) delete this; - return refcnt; - } + NS_INLINE_DECL_REFCOUNTING(RDFBindingSet) PRInt32 Count() const { return mCount; } diff --git a/db/sqlite3/README.MOZILLA b/db/sqlite3/README.MOZILLA index 078ac715cb7a..a90db532cc52 100644 --- a/db/sqlite3/README.MOZILLA +++ b/db/sqlite3/README.MOZILLA @@ -1,4 +1,4 @@ -This is sqlite 3.6.23 +This is sqlite 3.6.23.1 -- Shawn Wilsher , 03/2010 diff --git a/db/sqlite3/src/sqlite3.c b/db/sqlite3/src/sqlite3.c index 0e473c6ef700..8c44ff4b39a5 100644 --- a/db/sqlite3/src/sqlite3.c +++ b/db/sqlite3/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.6.23. By combining all the individual C code files into this +** version 3.6.23.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a one translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -628,9 +628,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.6.23" +#define SQLITE_VERSION "3.6.23.1" #define SQLITE_VERSION_NUMBER 3006023 -#define SQLITE_SOURCE_ID "2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d" +#define SQLITE_SOURCE_ID "2010-03-26 22:28:06 b078b588d617e07886ad156e9f54ade6d823568e" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -10868,6 +10868,393 @@ SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; /************** End of global.c **********************************************/ +/************** Begin file ctime.c *******************************************/ +/* +** 2010 February 23 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements routines used to report what compile-time options +** SQLite was built with. +*/ + +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + + +/* +** An array of names of all compile-time options. This array should +** be sorted A-Z. +** +** This array looks large, but in a typical installation actually uses +** only a handful of compile-time options, so most times this array is usually +** rather short and uses little memory space. +*/ +static const char * const azCompileOpt[] = { + +/* These macros are provided to "stringify" the value of the define +** for those options in which the value is meaningful. */ +#define CTIMEOPT_VAL_(opt) #opt +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + +#ifdef SQLITE_32BIT_ROWID + "32BIT_ROWID", +#endif +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC + "4_BYTE_ALIGNED_MALLOC", +#endif +#ifdef SQLITE_CASE_SENSITIVE_LIKE + "CASE_SENSITIVE_LIKE", +#endif +#ifdef SQLITE_CHECK_PAGES + "CHECK_PAGES", +#endif +#ifdef SQLITE_COVERAGE_TEST + "COVERAGE_TEST", +#endif +#ifdef SQLITE_DEBUG + "DEBUG", +#endif +#ifdef SQLITE_DEFAULT_LOCKING_MODE + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), +#endif +#ifdef SQLITE_DISABLE_DIRSYNC + "DISABLE_DIRSYNC", +#endif +#ifdef SQLITE_DISABLE_LFS + "DISABLE_LFS", +#endif +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + "ENABLE_ATOMIC_WRITE", +#endif +#ifdef SQLITE_ENABLE_CEROD + "ENABLE_CEROD", +#endif +#ifdef SQLITE_ENABLE_COLUMN_METADATA + "ENABLE_COLUMN_METADATA", +#endif +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + "ENABLE_EXPENSIVE_ASSERT", +#endif +#ifdef SQLITE_ENABLE_FTS1 + "ENABLE_FTS1", +#endif +#ifdef SQLITE_ENABLE_FTS2 + "ENABLE_FTS2", +#endif +#ifdef SQLITE_ENABLE_FTS3 + "ENABLE_FTS3", +#endif +#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS + "ENABLE_FTS3_PARENTHESIS", +#endif +#ifdef SQLITE_ENABLE_FTS4 + "ENABLE_FTS4", +#endif +#ifdef SQLITE_ENABLE_ICU + "ENABLE_ICU", +#endif +#ifdef SQLITE_ENABLE_IOTRACE + "ENABLE_IOTRACE", +#endif +#ifdef SQLITE_ENABLE_LOAD_EXTENSION + "ENABLE_LOAD_EXTENSION", +#endif +#ifdef SQLITE_ENABLE_LOCKING_STYLE + "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), +#endif +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + "ENABLE_MEMORY_MANAGEMENT", +#endif +#ifdef SQLITE_ENABLE_MEMSYS3 + "ENABLE_MEMSYS3", +#endif +#ifdef SQLITE_ENABLE_MEMSYS5 + "ENABLE_MEMSYS5", +#endif +#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK + "ENABLE_OVERSIZE_CELL_CHECK", +#endif +#ifdef SQLITE_ENABLE_RTREE + "ENABLE_RTREE", +#endif +#ifdef SQLITE_ENABLE_STAT2 + "ENABLE_STAT2", +#endif +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY + "ENABLE_UNLOCK_NOTIFY", +#endif +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT + "ENABLE_UPDATE_DELETE_LIMIT", +#endif +#ifdef SQLITE_HAS_CODEC + "HAS_CODEC", +#endif +#ifdef SQLITE_HAVE_ISNAN + "HAVE_ISNAN", +#endif +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + "HOMEGROWN_RECURSIVE_MUTEX", +#endif +#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS + "IGNORE_AFP_LOCK_ERRORS", +#endif +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS + "IGNORE_FLOCK_LOCK_ERRORS", +#endif +#ifdef SQLITE_INT64_TYPE + "INT64_TYPE", +#endif +#ifdef SQLITE_LOCK_TRACE + "LOCK_TRACE", +#endif +#ifdef SQLITE_MEMDEBUG + "MEMDEBUG", +#endif +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT + "MIXED_ENDIAN_64BIT_FLOAT", +#endif +#ifdef SQLITE_NO_SYNC + "NO_SYNC", +#endif +#ifdef SQLITE_OMIT_ALTERTABLE + "OMIT_ALTERTABLE", +#endif +#ifdef SQLITE_OMIT_ANALYZE + "OMIT_ANALYZE", +#endif +#ifdef SQLITE_OMIT_ATTACH + "OMIT_ATTACH", +#endif +#ifdef SQLITE_OMIT_AUTHORIZATION + "OMIT_AUTHORIZATION", +#endif +#ifdef SQLITE_OMIT_AUTOINCREMENT + "OMIT_AUTOINCREMENT", +#endif +#ifdef SQLITE_OMIT_AUTOINIT + "OMIT_AUTOINIT", +#endif +#ifdef SQLITE_OMIT_AUTOVACUUM + "OMIT_AUTOVACUUM", +#endif +#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION + "OMIT_BETWEEN_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_BLOB_LITERAL + "OMIT_BLOB_LITERAL", +#endif +#ifdef SQLITE_OMIT_BTREECOUNT + "OMIT_BTREECOUNT", +#endif +#ifdef SQLITE_OMIT_BUILTIN_TEST + "OMIT_BUILTIN_TEST", +#endif +#ifdef SQLITE_OMIT_CAST + "OMIT_CAST", +#endif +#ifdef SQLITE_OMIT_CHECK + "OMIT_CHECK", +#endif +#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS + "OMIT_COMPILEOPTION_DIAGS", +#endif +#ifdef SQLITE_OMIT_COMPLETE + "OMIT_COMPLETE", +#endif +#ifdef SQLITE_OMIT_COMPOUND_SELECT + "OMIT_COMPOUND_SELECT", +#endif +#ifdef SQLITE_OMIT_DATETIME_FUNCS + "OMIT_DATETIME_FUNCS", +#endif +#ifdef SQLITE_OMIT_DECLTYPE + "OMIT_DECLTYPE", +#endif +#ifdef SQLITE_OMIT_DEPRECATED + "OMIT_DEPRECATED", +#endif +#ifdef SQLITE_OMIT_DISKIO + "OMIT_DISKIO", +#endif +#ifdef SQLITE_OMIT_EXPLAIN + "OMIT_EXPLAIN", +#endif +#ifdef SQLITE_OMIT_FLAG_PRAGMAS + "OMIT_FLAG_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_FLOATING_POINT + "OMIT_FLOATING_POINT", +#endif +#ifdef SQLITE_OMIT_FOREIGN_KEY + "OMIT_FOREIGN_KEY", +#endif +#ifdef SQLITE_OMIT_GET_TABLE + "OMIT_GET_TABLE", +#endif +#ifdef SQLITE_OMIT_GLOBALRECOVER + "OMIT_GLOBALRECOVER", +#endif +#ifdef SQLITE_OMIT_INCRBLOB + "OMIT_INCRBLOB", +#endif +#ifdef SQLITE_OMIT_INTEGRITY_CHECK + "OMIT_INTEGRITY_CHECK", +#endif +#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION + "OMIT_LIKE_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_LOAD_EXTENSION + "OMIT_LOAD_EXTENSION", +#endif +#ifdef SQLITE_OMIT_LOCALTIME + "OMIT_LOCALTIME", +#endif +#ifdef SQLITE_OMIT_LOOKASIDE + "OMIT_LOOKASIDE", +#endif +#ifdef SQLITE_OMIT_MEMORYDB + "OMIT_MEMORYDB", +#endif +#ifdef SQLITE_OMIT_OR_OPTIMIZATION + "OMIT_OR_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_PAGER_PRAGMAS + "OMIT_PAGER_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_PRAGMA + "OMIT_PRAGMA", +#endif +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK + "OMIT_PROGRESS_CALLBACK", +#endif +#ifdef SQLITE_OMIT_QUICKBALANCE + "OMIT_QUICKBALANCE", +#endif +#ifdef SQLITE_OMIT_REINDEX + "OMIT_REINDEX", +#endif +#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS + "OMIT_SCHEMA_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + "OMIT_SCHEMA_VERSION_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_SHARED_CACHE + "OMIT_SHARED_CACHE", +#endif +#ifdef SQLITE_OMIT_SUBQUERY + "OMIT_SUBQUERY", +#endif +#ifdef SQLITE_OMIT_TCL_VARIABLE + "OMIT_TCL_VARIABLE", +#endif +#ifdef SQLITE_OMIT_TEMPDB + "OMIT_TEMPDB", +#endif +#ifdef SQLITE_OMIT_TRACE + "OMIT_TRACE", +#endif +#ifdef SQLITE_OMIT_TRIGGER + "OMIT_TRIGGER", +#endif +#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION + "OMIT_TRUNCATE_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_UTF16 + "OMIT_UTF16", +#endif +#ifdef SQLITE_OMIT_VACUUM + "OMIT_VACUUM", +#endif +#ifdef SQLITE_OMIT_VIEW + "OMIT_VIEW", +#endif +#ifdef SQLITE_OMIT_VIRTUALTABLE + "OMIT_VIRTUALTABLE", +#endif +#ifdef SQLITE_OMIT_WSD + "OMIT_WSD", +#endif +#ifdef SQLITE_OMIT_XFER_OPT + "OMIT_XFER_OPT", +#endif +#ifdef SQLITE_PERFORMANCE_TRACE + "PERFORMANCE_TRACE", +#endif +#ifdef SQLITE_PROXY_DEBUG + "PROXY_DEBUG", +#endif +#ifdef SQLITE_SECURE_DELETE + "SECURE_DELETE", +#endif +#ifdef SQLITE_SMALL_STACK + "SMALL_STACK", +#endif +#ifdef SQLITE_SOUNDEX + "SOUNDEX", +#endif +#ifdef SQLITE_TCL + "TCL", +#endif +#ifdef SQLITE_TEMP_STORE + "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), +#endif +#ifdef SQLITE_TEST + "TEST", +#endif +#ifdef SQLITE_THREADSAFE + "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), +#endif +#ifdef SQLITE_USE_ALLOCA + "USE_ALLOCA", +#endif +#ifdef SQLITE_ZERO_MALLOC + "ZERO_MALLOC" +#endif +}; + +/* +** Given the name of a compile-time option, return true if that option +** was used and false if not. +** +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix +** is not required for a match. +*/ +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ + int i, n; + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; + n = sqlite3Strlen30(zOptName); + + /* Since ArraySize(azCompileOpt) is normally in single digits, a + ** linear search is adequate. No need for a binary search. */ + for(i=0; i=0 && Njfd, zMaster, pPager->pVfs->mxPathname+1); testcase( rc!=SQLITE_OK ); } + if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){ + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + } if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager, zMaster[0]!='\0'); testcase( rc!=SQLITE_OK ); @@ -71127,395 +71517,6 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ } /************** End of callback.c ********************************************/ -/************** Begin file ctime.c *******************************************/ -/* -** 2010 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements routines used to report what compile-time options -** SQLite was built with. -*/ - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - - -/* -** An array of names of all compile-time options. This array should -** be sorted A-Z. -** -** This array looks large, but in a typical installation actually uses -** only a handful of compile-time options, so most times this array is usually -** rather short and uses little memory space. -*/ -static const char * const azCompileOpt[] = { - -/* These macros are provided to "stringify" the value of the define -** for those options in which the value is meaningful. */ -#define CTIMEOPT_VAL_(opt) #opt -#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) - -#ifdef SQLITE_32BIT_ROWID - "32BIT_ROWID", -#endif -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC - "4_BYTE_ALIGNED_MALLOC", -#endif -#ifdef SQLITE_CASE_SENSITIVE_LIKE - "CASE_SENSITIVE_LIKE", -#endif -#ifdef SQLITE_CHECK_PAGES - "CHECK_PAGES", -#endif -#ifdef SQLITE_COVERAGE_TEST - "COVERAGE_TEST", -#endif -#ifdef SQLITE_DEBUG - "DEBUG", -#endif -#ifdef SQLITE_DEFAULT_LOCKING_MODE - "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), -#endif -#ifdef SQLITE_DISABLE_DIRSYNC - "DISABLE_DIRSYNC", -#endif -#ifdef SQLITE_DISABLE_LFS - "DISABLE_LFS", -#endif -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - "ENABLE_ATOMIC_WRITE", -#endif -#ifdef SQLITE_ENABLE_CEROD - "ENABLE_CEROD", -#endif -#ifdef SQLITE_ENABLE_COLUMN_METADATA - "ENABLE_COLUMN_METADATA", -#endif -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - "ENABLE_EXPENSIVE_ASSERT", -#endif -#ifdef SQLITE_ENABLE_FTS1 - "ENABLE_FTS1", -#endif -#ifdef SQLITE_ENABLE_FTS2 - "ENABLE_FTS2", -#endif -#ifdef SQLITE_ENABLE_FTS3 - "ENABLE_FTS3", -#endif -#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS - "ENABLE_FTS3_PARENTHESIS", -#endif -#if 0 /* Disabled because FTS4 is not ready for publication */ -#ifdef SQLITE_ENABLE_FTS4 - "ENABLE_FTS4", -#endif -#endif -#ifdef SQLITE_ENABLE_ICU - "ENABLE_ICU", -#endif -#ifdef SQLITE_ENABLE_IOTRACE - "ENABLE_IOTRACE", -#endif -#ifdef SQLITE_ENABLE_LOAD_EXTENSION - "ENABLE_LOAD_EXTENSION", -#endif -#ifdef SQLITE_ENABLE_LOCKING_STYLE - "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), -#endif -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - "ENABLE_MEMORY_MANAGEMENT", -#endif -#ifdef SQLITE_ENABLE_MEMSYS3 - "ENABLE_MEMSYS3", -#endif -#ifdef SQLITE_ENABLE_MEMSYS5 - "ENABLE_MEMSYS5", -#endif -#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK - "ENABLE_OVERSIZE_CELL_CHECK", -#endif -#ifdef SQLITE_ENABLE_RTREE - "ENABLE_RTREE", -#endif -#ifdef SQLITE_ENABLE_STAT2 - "ENABLE_STAT2", -#endif -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - "ENABLE_UNLOCK_NOTIFY", -#endif -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - "ENABLE_UPDATE_DELETE_LIMIT", -#endif -#ifdef SQLITE_HAS_CODEC - "HAS_CODEC", -#endif -#ifdef SQLITE_HAVE_ISNAN - "HAVE_ISNAN", -#endif -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX - "HOMEGROWN_RECURSIVE_MUTEX", -#endif -#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS - "IGNORE_AFP_LOCK_ERRORS", -#endif -#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - "IGNORE_FLOCK_LOCK_ERRORS", -#endif -#ifdef SQLITE_INT64_TYPE - "INT64_TYPE", -#endif -#ifdef SQLITE_LOCK_TRACE - "LOCK_TRACE", -#endif -#ifdef SQLITE_MEMDEBUG - "MEMDEBUG", -#endif -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT - "MIXED_ENDIAN_64BIT_FLOAT", -#endif -#ifdef SQLITE_NO_SYNC - "NO_SYNC", -#endif -#ifdef SQLITE_OMIT_ALTERTABLE - "OMIT_ALTERTABLE", -#endif -#ifdef SQLITE_OMIT_ANALYZE - "OMIT_ANALYZE", -#endif -#ifdef SQLITE_OMIT_ATTACH - "OMIT_ATTACH", -#endif -#ifdef SQLITE_OMIT_AUTHORIZATION - "OMIT_AUTHORIZATION", -#endif -#ifdef SQLITE_OMIT_AUTOINCREMENT - "OMIT_AUTOINCREMENT", -#endif -#ifdef SQLITE_OMIT_AUTOINIT - "OMIT_AUTOINIT", -#endif -#ifdef SQLITE_OMIT_AUTOVACUUM - "OMIT_AUTOVACUUM", -#endif -#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION - "OMIT_BETWEEN_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_BLOB_LITERAL - "OMIT_BLOB_LITERAL", -#endif -#ifdef SQLITE_OMIT_BTREECOUNT - "OMIT_BTREECOUNT", -#endif -#ifdef SQLITE_OMIT_BUILTIN_TEST - "OMIT_BUILTIN_TEST", -#endif -#ifdef SQLITE_OMIT_CAST - "OMIT_CAST", -#endif -#ifdef SQLITE_OMIT_CHECK - "OMIT_CHECK", -#endif -#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS - "OMIT_COMPILEOPTION_DIAGS", -#endif -#ifdef SQLITE_OMIT_COMPLETE - "OMIT_COMPLETE", -#endif -#ifdef SQLITE_OMIT_COMPOUND_SELECT - "OMIT_COMPOUND_SELECT", -#endif -#ifdef SQLITE_OMIT_DATETIME_FUNCS - "OMIT_DATETIME_FUNCS", -#endif -#ifdef SQLITE_OMIT_DECLTYPE - "OMIT_DECLTYPE", -#endif -#ifdef SQLITE_OMIT_DEPRECATED - "OMIT_DEPRECATED", -#endif -#ifdef SQLITE_OMIT_DISKIO - "OMIT_DISKIO", -#endif -#ifdef SQLITE_OMIT_EXPLAIN - "OMIT_EXPLAIN", -#endif -#ifdef SQLITE_OMIT_FLAG_PRAGMAS - "OMIT_FLAG_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_FLOATING_POINT - "OMIT_FLOATING_POINT", -#endif -#ifdef SQLITE_OMIT_FOREIGN_KEY - "OMIT_FOREIGN_KEY", -#endif -#ifdef SQLITE_OMIT_GET_TABLE - "OMIT_GET_TABLE", -#endif -#ifdef SQLITE_OMIT_GLOBALRECOVER - "OMIT_GLOBALRECOVER", -#endif -#ifdef SQLITE_OMIT_INCRBLOB - "OMIT_INCRBLOB", -#endif -#ifdef SQLITE_OMIT_INTEGRITY_CHECK - "OMIT_INTEGRITY_CHECK", -#endif -#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION - "OMIT_LIKE_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_LOAD_EXTENSION - "OMIT_LOAD_EXTENSION", -#endif -#ifdef SQLITE_OMIT_LOCALTIME - "OMIT_LOCALTIME", -#endif -#ifdef SQLITE_OMIT_LOOKASIDE - "OMIT_LOOKASIDE", -#endif -#ifdef SQLITE_OMIT_MEMORYDB - "OMIT_MEMORYDB", -#endif -#ifdef SQLITE_OMIT_OR_OPTIMIZATION - "OMIT_OR_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_PAGER_PRAGMAS - "OMIT_PAGER_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_PRAGMA - "OMIT_PRAGMA", -#endif -#ifdef SQLITE_OMIT_PROGRESS_CALLBACK - "OMIT_PROGRESS_CALLBACK", -#endif -#ifdef SQLITE_OMIT_QUICKBALANCE - "OMIT_QUICKBALANCE", -#endif -#ifdef SQLITE_OMIT_REINDEX - "OMIT_REINDEX", -#endif -#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS - "OMIT_SCHEMA_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - "OMIT_SCHEMA_VERSION_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_SHARED_CACHE - "OMIT_SHARED_CACHE", -#endif -#ifdef SQLITE_OMIT_SUBQUERY - "OMIT_SUBQUERY", -#endif -#ifdef SQLITE_OMIT_TCL_VARIABLE - "OMIT_TCL_VARIABLE", -#endif -#ifdef SQLITE_OMIT_TEMPDB - "OMIT_TEMPDB", -#endif -#ifdef SQLITE_OMIT_TRACE - "OMIT_TRACE", -#endif -#ifdef SQLITE_OMIT_TRIGGER - "OMIT_TRIGGER", -#endif -#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION - "OMIT_TRUNCATE_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_UTF16 - "OMIT_UTF16", -#endif -#ifdef SQLITE_OMIT_VACUUM - "OMIT_VACUUM", -#endif -#ifdef SQLITE_OMIT_VIEW - "OMIT_VIEW", -#endif -#ifdef SQLITE_OMIT_VIRTUALTABLE - "OMIT_VIRTUALTABLE", -#endif -#ifdef SQLITE_OMIT_WSD - "OMIT_WSD", -#endif -#ifdef SQLITE_OMIT_XFER_OPT - "OMIT_XFER_OPT", -#endif -#ifdef SQLITE_PERFORMANCE_TRACE - "PERFORMANCE_TRACE", -#endif -#ifdef SQLITE_PROXY_DEBUG - "PROXY_DEBUG", -#endif -#ifdef SQLITE_SECURE_DELETE - "SECURE_DELETE", -#endif -#ifdef SQLITE_SMALL_STACK - "SMALL_STACK", -#endif -#ifdef SQLITE_SOUNDEX - "SOUNDEX", -#endif -#ifdef SQLITE_TCL - "TCL", -#endif -#ifdef SQLITE_TEMP_STORE - "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), -#endif -#ifdef SQLITE_TEST - "TEST", -#endif -#ifdef SQLITE_THREADSAFE - "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), -#endif -#ifdef SQLITE_USE_ALLOCA - "USE_ALLOCA", -#endif -#ifdef SQLITE_ZERO_MALLOC - "ZERO_MALLOC" -#endif -}; - -/* -** Given the name of a compile-time option, return true if that option -** was used and false if not. -** -** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix -** is not required for a match. -*/ -SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ - int i, n; - if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; - n = sqlite3Strlen30(zOptName); - - /* Since ArraySize(azCompileOpt) is normally in single digits, a - ** linear search is adequate. No need for a binary search. */ - for(i=0; i=0 && NpTokenizer, p->azColumn, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr ); - if( rc!=SQLITE_OK ) return rc; + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_ERROR ){ + p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]", + zQuery); + } + return rc; + } rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0); pCsr->pNextId = pCsr->aDoclist; @@ -102280,13 +102302,11 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ rc = sqlite3_create_module_v2( db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); -#if 0 /* FTS4 is disabled in 3.6.23 since it is not yet ready for publication */ if( rc==SQLITE_OK ){ rc = sqlite3_create_module_v2( db, "fts4", &fts3Module, (void *)pHash, 0 ); } -#endif /* disable FTS4 */ return rc; } @@ -105167,9 +105187,9 @@ static int fts3SqlStmt( /* 5 */ "DELETE FROM %Q.'%q_docsize'", /* 6 */ "DELETE FROM %Q.'%q_stat'", /* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", -/* 8 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", +/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", /* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", -/* 10 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", +/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", /* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", /* Return segments in order from oldest to newest.*/ @@ -108728,11 +108748,13 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart ); rc = fts3StringAppend(&res, aBuffer, -1); + }else if( rc==SQLITE_DONE ){ + rc = SQLITE_CORRUPT; } } } if( rc==SQLITE_DONE ){ - rc = SQLITE_CORRUPT; + rc = SQLITE_OK; } pMod->xClose(pC); diff --git a/db/sqlite3/src/sqlite3.h b/db/sqlite3/src/sqlite3.h index ae45d818fade..d72fdbd51af3 100644 --- a/db/sqlite3/src/sqlite3.h +++ b/db/sqlite3/src/sqlite3.h @@ -107,9 +107,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.6.23" +#define SQLITE_VERSION "3.6.23.1" #define SQLITE_VERSION_NUMBER 3006023 -#define SQLITE_SOURCE_ID "2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d" +#define SQLITE_SOURCE_ID "2010-03-26 22:28:06 b078b588d617e07886ad156e9f54ade6d823568e" /* ** CAPI3REF: Run-Time Library Version Numbers diff --git a/docshell/test/browser/browser_bug134911.js b/docshell/test/browser/browser_bug134911.js index 5a2e9dcdb9c3..368439b130a0 100644 --- a/docshell/test/browser/browser_bug134911.js +++ b/docshell/test/browser/browser_bug134911.js @@ -1,6 +1,3 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - /* The test text decoded correctly as Shift_JIS */ const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059"; @@ -42,6 +39,5 @@ function afterChangeCharset() { } function url(spec) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return ios.newURI(spec, null, null); + return Services.io.newURI(spec, null, null); } diff --git a/docshell/test/browser/browser_bug349769.js b/docshell/test/browser/browser_bug349769.js index eecf6bf892ec..35eef985df5c 100644 --- a/docshell/test/browser/browser_bug349769.js +++ b/docshell/test/browser/browser_bug349769.js @@ -3,8 +3,7 @@ function test() { var newTab; var newBrowser; - const secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager); + const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); var iteration = 1; const uris = [undefined, "about:blank"]; var uri; diff --git a/docshell/test/browser/browser_bug388121-1.js b/docshell/test/browser/browser_bug388121-1.js index 54c3140e9878..f19c2bbff526 100644 --- a/docshell/test/browser/browser_bug388121-1.js +++ b/docshell/test/browser/browser_bug388121-1.js @@ -3,8 +3,7 @@ function test() { var newTab; var newBrowser; - const secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager); + const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); function testLoad(event) { newBrowser.removeEventListener("load", testLoad, true); diff --git a/docshell/test/browser/browser_bug388121-2.js b/docshell/test/browser/browser_bug388121-2.js index 5f5d8c422246..6c050d971a39 100644 --- a/docshell/test/browser/browser_bug388121-2.js +++ b/docshell/test/browser/browser_bug388121-2.js @@ -2,8 +2,7 @@ function test() { waitForExplicitFinish(); var w; - const secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager); + const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); var iteration = 1; const uris = ["", "about:blank"]; var uri; diff --git a/docshell/test/browser/browser_bug92473.js b/docshell/test/browser/browser_bug92473.js index 2ed330b09085..026048e963d8 100644 --- a/docshell/test/browser/browser_bug92473.js +++ b/docshell/test/browser/browser_bug92473.js @@ -1,6 +1,3 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - /* The test text decoded correctly as Shift_JIS */ const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059"; @@ -11,8 +8,7 @@ const wrongText="\u0453\u2020\u0453\u006A\u0453\u0052\u0403\u005B\u0453\u0068\u2 var testPage; function url(spec) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return ios.newURI(spec, null, null); + return Services.io.newURI(spec, null, null); } function testContent(text) { diff --git a/docshell/test/unit/head_docshell.js b/docshell/test/unit/head_docshell.js index f893629eb946..cd3c0dc59862 100644 --- a/docshell/test/unit/head_docshell.js +++ b/docshell/test/unit/head_docshell.js @@ -67,7 +67,7 @@ var provider = { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/dom/plugins/PluginInstanceChild.cpp b/dom/plugins/PluginInstanceChild.cpp index c5c84757cbce..3ac521ffb148 100644 --- a/dom/plugins/PluginInstanceChild.cpp +++ b/dom/plugins/PluginInstanceChild.cpp @@ -80,6 +80,7 @@ using mozilla::gfx::SharedDIB; #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg") #elif defined(XP_MACOSX) #include +#include "nsPluginUtilsOSX.h" #endif // defined(XP_MACOSX) PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface, @@ -99,6 +100,10 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface, , mWinlessPopupSurrogateHWND(0) #endif // OS_WIN , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex") +#if defined(OS_MACOSX) + , mShColorSpace(NULL) + , mShContext(NULL) +#endif { memset(&mWindow, 0, sizeof(mWindow)); mData.ndata = (void*) this; @@ -127,6 +132,14 @@ PluginInstanceChild::~PluginInstanceChild() #if defined(OS_WIN) DestroyPluginWindow(); #endif +#if defined(OS_MACOSX) + if (mShColorSpace) { + ::CGColorSpaceRelease(mShColorSpace); + } + if (mShContext) { + ::CGContextRelease(mShContext); + } +#endif } void @@ -585,28 +598,34 @@ PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, PLUGIN_LOG_DEBUG_FUNCTION; AssertPluginThread(); - // We return access to the shared memory buffer after returning. - NPCocoaEvent evcopy = event.event; if (evcopy.type == NPCocoaEventDrawRect) { - CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if (!cSpace) { - PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); - *handled = false; - *rtnmem = mem; - return true; - } - void* cgContextByte = mem.get(); - CGContextRef ctxt = ::CGBitmapContextCreate(cgContextByte, mWindow.width, mWindow.height, 8, mWindow.width * 4, cSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); - ::CGColorSpaceRelease(cSpace); - if (!ctxt) { - PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); - *handled = false; - *rtnmem = mem; - return true; + if (!mShColorSpace) { + mShColorSpace = CreateSystemColorSpace(); + if (!mShColorSpace) { + PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); + *handled = false; + *rtnmem = mem; + return true; + } } - evcopy.data.draw.context = ctxt; + if (!mShContext) { + void* cgContextByte = mem.get(); + mShContext = ::CGBitmapContextCreate(cgContextByte, + mWindow.width, mWindow.height, 8, + mWindow.width * 4, mShColorSpace, + kCGImageAlphaPremultipliedFirst | + kCGBitmapByteOrder32Host); + + if (!mShContext) { + PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); + *handled = false; + *rtnmem = mem; + return true; + } + } + evcopy.data.draw.context = mShContext; } else { PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem.")); *handled = false; @@ -620,11 +639,6 @@ PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, *handled = mPluginIface->event(&mData, reinterpret_cast(&evcopy)); } - // Some events need cleaning up. - if (evcopy.type == NPCocoaEventDrawRect) { - ::CGContextRelease(evcopy.data.draw.context); - } - *rtnmem = mem; return true; } @@ -779,6 +793,13 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) mWindow.clipRect = aWindow.clipRect; mWindow.type = aWindow.type; + if (mShContext) { + // Release the shared context so that it is reallocated + // with the new size. + ::CGContextRelease(mShContext); + mShContext = NULL; + } + if (mPluginIface->setwindow) (void) mPluginIface->setwindow(&mData, &mWindow); diff --git a/dom/plugins/PluginInstanceChild.h b/dom/plugins/PluginInstanceChild.h index ad4ffeebfe43..47bee12bc60b 100644 --- a/dom/plugins/PluginInstanceChild.h +++ b/dom/plugins/PluginInstanceChild.h @@ -320,6 +320,11 @@ private: HBITMAP bmp; } mAlphaExtract; #endif // defined(OS_WIN) +#if defined(OS_MACOSX) +private: + CGColorSpaceRef mShColorSpace; + CGContextRef mShContext; +#endif }; } // namespace plugins diff --git a/dom/plugins/PluginInstanceParent.cpp b/dom/plugins/PluginInstanceParent.cpp index b8ce74cb7fd4..0e4e6e7b7352 100644 --- a/dom/plugins/PluginInstanceParent.cpp +++ b/dom/plugins/PluginInstanceParent.cpp @@ -61,6 +61,7 @@ UINT gOOPPStopNativeLoopEvent = #include #elif defined(XP_MACOSX) #include +#include "nsPluginUtilsOSX.h" #endif // defined(XP_MACOSX) using namespace mozilla::plugins; @@ -80,6 +81,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent, #if defined(XP_MACOSX) , mShWidth(0) , mShHeight(0) + , mShColorSpace(NULL) #endif { } @@ -93,6 +95,9 @@ PluginInstanceParent::~PluginInstanceParent() NS_ASSERTION(!(mPluginHWND || mPluginWndProc), "Subclass was not reset correctly before the dtor was reached!"); #endif +#if defined(OS_MACOSX) + ::CGColorSpaceRelease(mShColorSpace); +#endif } bool @@ -693,15 +698,16 @@ PluginInstanceParent::NPP_HandleEvent(void* event) char* shContextByte = mShSurface.get(); - CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if (!cSpace) { + if (!mShColorSpace) { + mShColorSpace = CreateSystemColorSpace(); + } + if (!mShColorSpace) { PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); return true; } CGContextRef shContext = ::CGBitmapContextCreate(shContextByte, - mShWidth, mShHeight, 8, mShWidth*4, cSpace, + mShWidth, mShHeight, 8, mShWidth*4, mShColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); - ::CGColorSpaceRelease(cSpace); if (!shContext) { PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); return true; diff --git a/dom/plugins/PluginInstanceParent.h b/dom/plugins/PluginInstanceParent.h index 006860011e69..1e33f5a9b7db 100644 --- a/dom/plugins/PluginInstanceParent.h +++ b/dom/plugins/PluginInstanceParent.h @@ -285,6 +285,7 @@ private: Shmem mShSurface; size_t mShWidth; size_t mShHeight; + CGColorSpaceRef mShColorSpace; #endif // definied(OS_MACOSX) }; diff --git a/dom/src/geolocation/MaemoLocationProvider.cpp b/dom/src/geolocation/MaemoLocationProvider.cpp index 626d4f15d470..edd5be808c52 100644 --- a/dom/src/geolocation/MaemoLocationProvider.cpp +++ b/dom/src/geolocation/MaemoLocationProvider.cpp @@ -192,7 +192,6 @@ MaemoLocationProvider::MaemoLocationProvider() : mIgnoreMinorChanges(PR_FALSE), mPrevLat(0.0), mPrevLong(0.0), - mInterval(LOCATION_INTERVAL_5S), mIgnoreBigHErr(PR_TRUE), mMaxHErr(1000), mIgnoreBigVErr(PR_TRUE), @@ -294,11 +293,6 @@ MaemoLocationProvider::StartControl() mGPSControl = location_gpsd_control_get_default(); NS_ENSURE_TRUE(mGPSControl, NS_ERROR_FAILURE); - g_object_set(G_OBJECT(mGPSControl), - "preferred-interval", mInterval, - "preferred-method", LOCATION_METHOD_USER_SELECTED, - NULL); - mControlError = g_signal_connect(mGPSControl, "error", G_CALLBACK(ControlError), this); @@ -330,43 +324,9 @@ NS_IMETHODIMP MaemoLocationProvider::Startup() { nsresult rv(NS_OK); - PRInt32 freqVal = 5; nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); - if (prefs) { - rv = prefs->GetIntPref("geo.location_update_freq", &freqVal); - switch (freqVal) { - case 0: - mInterval = LOCATION_INTERVAL_DEFAULT; - break; - case 1: - mInterval = LOCATION_INTERVAL_1S; - break; - case 2: - mInterval = LOCATION_INTERVAL_2S; - break; - case 5: - mInterval = LOCATION_INTERVAL_5S; - break; - case 10: - mInterval = LOCATION_INTERVAL_10S; - break; - case 20: - mInterval = LOCATION_INTERVAL_20S; - break; - case 30: - mInterval = LOCATION_INTERVAL_30S; - break; - case 60: - mInterval = LOCATION_INTERVAL_60S; - break; - case 120: - mInterval = LOCATION_INTERVAL_120S; - break; - default: - mInterval = LOCATION_INTERVAL_DEFAULT; - break; - } - } + if (!prefs) + return NS_ERROR_FAILURE; rv = StartControl(); NS_ENSURE_SUCCESS(rv, rv); @@ -374,14 +334,12 @@ NS_IMETHODIMP MaemoLocationProvider::Startup() rv = StartDevice(); NS_ENSURE_SUCCESS(rv, rv); - if (prefs) - prefs->GetBoolPref("geo.herror.ignore.big", &mIgnoreBigHErr); + prefs->GetBoolPref("geo.herror.ignore.big", &mIgnoreBigHErr); if (mIgnoreBigHErr) prefs->GetIntPref("geo.herror.max.value", &mMaxHErr); - if (prefs) - prefs->GetBoolPref("geo.verror.ignore.big", &mIgnoreBigVErr); + prefs->GetBoolPref("geo.verror.ignore.big", &mIgnoreBigVErr); if (mIgnoreBigVErr) prefs->GetIntPref("geo.verror.max.value", &mMaxVErr); @@ -390,8 +348,7 @@ NS_IMETHODIMP MaemoLocationProvider::Startup() return NS_OK; PRInt32 update = 0; //0 second no timer created - if (prefs) - prefs->GetIntPref("geo.default.update", &update); + prefs->GetIntPref("geo.default.update", &update); if (!update) return NS_OK; diff --git a/dom/src/geolocation/MaemoLocationProvider.h b/dom/src/geolocation/MaemoLocationProvider.h index 2df739b6454c..780f1e955393 100644 --- a/dom/src/geolocation/MaemoLocationProvider.h +++ b/dom/src/geolocation/MaemoLocationProvider.h @@ -112,7 +112,6 @@ class MaemoLocationProvider : public nsIGeolocationProvider, double mPrevLat; double mPrevLong; - LocationGPSDControlInterval mInterval; PRBool mIgnoreBigHErr; PRInt32 mMaxHErr; PRBool mIgnoreBigVErr; diff --git a/dom/src/geolocation/Makefile.in b/dom/src/geolocation/Makefile.in index e8eb3d2f8f3d..c48c6a3e99ad 100644 --- a/dom/src/geolocation/Makefile.in +++ b/dom/src/geolocation/Makefile.in @@ -65,6 +65,11 @@ ifdef WINCE_WINDOWS_MOBILE CPPSRCS += WinMobileLocationProvider.cpp endif +ifdef MOZ_PLATFORM_MAEMO +CPPSRCS += MaemoLocationProvider.cpp +LOCAL_INCLUDES += $(MOZ_PLATFORM_MAEMO_CFLAGS) +endif + EXTRA_COMPONENTS = \ NetworkGeolocationProvider.js \ GPSDGeolocationProvider.js \ diff --git a/dom/src/geolocation/nsGeolocation.cpp b/dom/src/geolocation/nsGeolocation.cpp index 00cd3af3d9d3..6d07f66aa71a 100644 --- a/dom/src/geolocation/nsGeolocation.cpp +++ b/dom/src/geolocation/nsGeolocation.cpp @@ -57,6 +57,10 @@ #include "WinMobileLocationProvider.h" #endif +#ifdef MOZ_PLATFORM_MAEMO +#include "MaemoLocationProvider.h" +#endif + #include "nsIDOMDocument.h" #include "nsIDocument.h" @@ -406,12 +410,17 @@ nsresult nsGeolocationService::Init() // we should move these providers outside of this file! dft - // if WINCE, see if we should try the WINCE location provider #ifdef WINCE_WINDOWS_MOBILE provider = new WinMobileLocationProvider(); if (provider) mProviders.AppendObject(provider); #endif + +#ifdef MOZ_PLATFORM_MAEMO + provider = new MaemoLocationProvider(); + if (provider) + mProviders.AppendObject(provider); +#endif return NS_OK; } diff --git a/editor/composer/src/crashtests/428844-1-inner.xhtml b/editor/composer/src/crashtests/428844-1-inner.xhtml index 905d38e2d8f5..1cc72d085699 100644 --- a/editor/composer/src/crashtests/428844-1-inner.xhtml +++ b/editor/composer/src/crashtests/428844-1-inner.xhtml @@ -1,4 +1,4 @@ - + diff --git a/editor/composer/src/crashtests/428844-1.html b/editor/composer/src/crashtests/428844-1.html index 11143ab72a80..1815118d235e 100644 --- a/editor/composer/src/crashtests/428844-1.html +++ b/editor/composer/src/crashtests/428844-1.html @@ -4,10 +4,11 @@ function boom() { var iframe = document.getElementById('inner'); iframe.src = iframe.src; + dump("Outer onload\n"); } - diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index a3759ceeebde..b5d674be34b4 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -42,6 +42,8 @@ #include "nsRegion.h" #include "nsPoint.h" #include "nsRect.h" +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" #include "gfx3DMatrix.h" class gfxContext; @@ -106,7 +108,7 @@ class ImageContainer; * root layer, and each container layer holds a reference to its children. */ class THEBES_API LayerManager { - THEBES_INLINE_DECL_REFCOUNTING(LayerManager) + NS_INLINE_DECL_REFCOUNTING(LayerManager) public: enum LayersBackend { @@ -181,7 +183,7 @@ public: * surface. */ class THEBES_API Layer { - THEBES_INLINE_DECL_REFCOUNTING(Layer) + NS_INLINE_DECL_REFCOUNTING(Layer) public: virtual ~Layer() {} diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp index 01028a37f56a..673b05107220 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -132,48 +132,57 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) * Setup our temporary texture for rendering the contents of this container. */ GLuint containerSurface; - - sglWrapper.GenTextures(1, &containerSurface); - sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); - sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D, - 0, - LOCAL_GL_RGBA, - mVisibleRect.width, - mVisibleRect.height, - 0, - LOCAL_GL_BGRA, - LOCAL_GL_UNSIGNED_BYTE, - NULL); - - /** - * Create the framebuffer and bind it to make our content render into our - * framebuffer. - */ GLuint frameBuffer; - sglWrapper.GenFramebuffersEXT(1, &frameBuffer); - sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, frameBuffer); - sglWrapper.FramebufferTexture2DEXT(LOCAL_GL_FRAMEBUFFER_EXT, - LOCAL_GL_COLOR_ATTACHMENT0_EXT, - LOCAL_GL_TEXTURE_2D, - containerSurface, - 0); - RGBLayerProgram *rgbProgram = static_cast(mManager)->GetRGBLayerProgram(); YCbCrLayerProgram *yCbCrProgram = static_cast(mManager)->GetYCbCrLayerProgram(); - /** - * Store old shader program variables and set the ones used for rendering - * this container's content. - */ - - rgbProgram->Activate(); - rgbProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, - (GLfloat)GetVisibleRect().y); - yCbCrProgram->Activate(); - yCbCrProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, - (GLfloat)GetVisibleRect().y); + if (GetOpacity() != 1.0) { + sglWrapper.GenTextures(1, &containerSurface); + sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); + sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + LOCAL_GL_RGBA, + mVisibleRect.width, + mVisibleRect.height, + 0, + LOCAL_GL_BGRA, + LOCAL_GL_UNSIGNED_BYTE, + NULL); + sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); + sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); + + /** + * Create the framebuffer and bind it to make our content render into our + * framebuffer. + */ + sglWrapper.GenFramebuffersEXT(1, &frameBuffer); + sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, frameBuffer); + sglWrapper.FramebufferTexture2DEXT(LOCAL_GL_FRAMEBUFFER_EXT, + LOCAL_GL_COLOR_ATTACHMENT0_EXT, + LOCAL_GL_TEXTURE_2D, + containerSurface, + 0); + + NS_ASSERTION( + sglWrapper.CheckFramebufferStatusEXT(LOCAL_GL_FRAMEBUFFER_EXT) == + LOCAL_GL_FRAMEBUFFER_COMPLETE, "Error setting up framebuffer."); + + /** + * Store old shader program variables and set the ones used for rendering + * this container's content. + */ + + rgbProgram->Activate(); + rgbProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, + (GLfloat)GetVisibleRect().y); + yCbCrProgram->Activate(); + yCbCrProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, + (GLfloat)GetVisibleRect().y); + } else { + frameBuffer = aPreviousFrameBuffer; + } /** * Render this container's contents. @@ -194,45 +203,47 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) layerToRender = layerToRender->GetNextSibling(); } - // Unbind the current framebuffer and rebind the previous one. - sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, aPreviousFrameBuffer); - sglWrapper.DeleteFramebuffersEXT(1, &frameBuffer); + if (GetOpacity() != 1.0) { + // Unbind the current framebuffer and rebind the previous one. + sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, aPreviousFrameBuffer); + sglWrapper.DeleteFramebuffersEXT(1, &frameBuffer); - // Restore old shader program variables. - yCbCrProgram->Activate(); - yCbCrProgram->PopRenderTargetOffset(); + // Restore old shader program variables. + yCbCrProgram->Activate(); + yCbCrProgram->PopRenderTargetOffset(); - rgbProgram->Activate(); - rgbProgram->PopRenderTargetOffset(); + rgbProgram->Activate(); + rgbProgram->PopRenderTargetOffset(); - /** - * Render the contents of this container to our destination. - */ - float quadTransform[4][4]; - /* - * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position - * and size. - */ - memset(&quadTransform, 0, sizeof(quadTransform)); - quadTransform[0][0] = (float)GetVisibleRect().width; - quadTransform[1][1] = (float)GetVisibleRect().height; - quadTransform[2][2] = 1.0f; - quadTransform[3][0] = (float)GetVisibleRect().x; - quadTransform[3][1] = (float)GetVisibleRect().y; - quadTransform[3][3] = 1.0f; + /** + * Render the contents of this container to our destination. + */ + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)GetVisibleRect().width; + quadTransform[1][1] = (float)GetVisibleRect().height; + quadTransform[2][2] = 1.0f; + quadTransform[3][0] = (float)GetVisibleRect().x; + quadTransform[3][1] = (float)GetVisibleRect().y; + quadTransform[3][3] = 1.0f; - rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]); + rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]); - sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); + sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); - rgbProgram->SetLayerOpacity(GetOpacity()); - rgbProgram->SetLayerTransform(&mTransform._11); - rgbProgram->Apply(); + rgbProgram->SetLayerOpacity(GetOpacity()); + rgbProgram->SetLayerTransform(&mTransform._11); + rgbProgram->Apply(); - sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); - // Clean up resources. - sglWrapper.DeleteTextures(1, &containerSurface); + // Clean up resources. + sglWrapper.DeleteTextures(1, &containerSurface); + } } } /* layers */ diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index 1d53be97b571..d85d9099142a 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -214,7 +214,20 @@ PlanarYCbCrImageOGL::AllocateTextures() mManager->MakeCurrent(); sglWrapper.GenTextures(3, mTextures); - sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mData.mYStride); + GLint alignment; + + if (!((ptrdiff_t)mData.mYStride & 0x7) && !((ptrdiff_t)mData.mYChannel & 0x7)) { + alignment = 8; + } else if (!((ptrdiff_t)mData.mYStride & 0x3)) { + alignment = 4; + } else if (!((ptrdiff_t)mData.mYStride & 0x1)) { + alignment = 2; + } else { + alignment = 1; + } + + // Set texture alignment for Y plane. + sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment); sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[0]); @@ -232,8 +245,21 @@ PlanarYCbCrImageOGL::AllocateTextures() LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE, mData.mYChannel); + + if (!((ptrdiff_t)mData.mCbCrStride & 0x7) && + !((ptrdiff_t)mData.mCbChannel & 0x7) && + !((ptrdiff_t)mData.mCrChannel & 0x7)) { + alignment = 8; + } else if (!((ptrdiff_t)mData.mCbCrStride & 0x3)) { + alignment = 4; + } else if (!((ptrdiff_t)mData.mCbCrStride & 0x1)) { + alignment = 2; + } else { + alignment = 1; + } - sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mData.mCbCrStride); + // Set texture alignment for Cb/Cr plane + sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment); sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[1]); @@ -269,7 +295,8 @@ PlanarYCbCrImageOGL::AllocateTextures() LOCAL_GL_UNSIGNED_BYTE, mData.mCrChannel); - sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0); + // Reset alignment to default + sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); } void diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 92473d44b0c5..b6c50dc615ec 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -83,19 +83,7 @@ LayerManagerOGL::Initialize() { #ifdef XP_WIN mDC = (HDC)mWidget->GetNativeData(NS_NATIVE_GRAPHIC); - PIXELFORMATDESCRIPTOR pfd; - ZeroMemory(&pfd, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - pfd.cDepthBits = 0; - pfd.iLayerType = PFD_MAIN_PLANE; - int iFormat = ChoosePixelFormat(mDC, &pfd); - - SetPixelFormat(mDC, iFormat, &pfd); mContext = sglWrapper.wCreateContext(mDC); if (!mContext) { diff --git a/gfx/layers/opengl/glDefs.h b/gfx/layers/opengl/glDefs.h index 65168f1c19e2..278d45f96dee 100644 --- a/gfx/layers/opengl/glDefs.h +++ b/gfx/layers/opengl/glDefs.h @@ -3024,5 +3024,6 @@ typedef ptrdiff_t GLintptr; #define LOCAL_GL_FRAMEBUFFER_EXT 0x8D40 #define LOCAL_GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define LOCAL_GL_FRAMEBUFFER_COMPLETE 0x8CD5 #endif diff --git a/gfx/layers/opengl/glWrapper.cpp b/gfx/layers/opengl/glWrapper.cpp index f275cc84bd1a..b6c7f1b6850b 100644 --- a/gfx/layers/opengl/glWrapper.cpp +++ b/gfx/layers/opengl/glWrapper.cpp @@ -79,14 +79,32 @@ glWrapper::wCreateContext(HDC aDC) } wCreateContextInternal = (PFNWGLCREATECONTEXTPROC) - PR_FindSymbol(mOGLLibrary, "wglCreateContext"); + PR_FindFunctionSymbol(mOGLLibrary, "wglCreateContext"); wDeleteContext = (PFNWGLDELETECONTEXTPROC) - PR_FindSymbol(mOGLLibrary, "wglDeleteContext"); + PR_FindFunctionSymbol(mOGLLibrary, "wglDeleteContext"); wMakeCurrent = (PFNWGLMAKECURRENTPROC) - PR_FindSymbol(mOGLLibrary, "wglMakeCurrent"); + PR_FindFunctionSymbol(mOGLLibrary, "wglMakeCurrent"); wGetProcAddress = (PFNWGLGETPROCADDRESSPROC) - PR_FindSymbol(mOGLLibrary, "wglGetProcAddress"); + PR_FindFunctionSymbol(mOGLLibrary, "wglGetProcAddress"); } + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(pfd)); + + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cDepthBits = 0; + pfd.iLayerType = PFD_MAIN_PLANE; + int iFormat = ChoosePixelFormat(aDC, &pfd); + + /** + * We need to make sure we call SetPixelFormat -after- loading the OGL + * library, otherwise it can load/unload the dll and wglCreateContext + * will fail. + */ + SetPixelFormat(aDC, iFormat, &pfd); HGLRC retval = wCreateContextInternal(aDC); if (!retval) { @@ -170,6 +188,7 @@ glWrapper::EnsureInitialized() { (PRFuncPtr*) &BindFramebufferEXT, "glBindFramebufferEXT" }, { (PRFuncPtr*) &FramebufferTexture2DEXT, "glFramebufferTexture2DEXT" }, + { (PRFuncPtr*) &CheckFramebufferStatusEXT, "glCheckFramebufferStatusEXT" }, { (PRFuncPtr*) &BufferData, "glBufferData" }, diff --git a/gfx/layers/opengl/glWrapper.h b/gfx/layers/opengl/glWrapper.h index 8c0a8a5e2d40..ea28133bb309 100644 --- a/gfx/layers/opengl/glWrapper.h +++ b/gfx/layers/opengl/glWrapper.h @@ -103,7 +103,8 @@ public: GLenum, GLenum, GLuint, - GLint); + GLint); + typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum); typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum, GLsizeiptr, @@ -214,6 +215,8 @@ public: PFNGLGENFRAMEBUFFERSEXTPROC GenFramebuffersEXT; PFNGLDELETETEXTURESPROC DeleteTextures; PFNGLDELETEFRAMEBUFFERSEXTPROC DeleteFramebuffersEXT; + + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC CheckFramebufferStatusEXT; PFNGLBINDTEXTUREPROC BindTexture; PFNGLBINDBUFFERPROC BindBuffer; diff --git a/gfx/thebes/crashtests/crashtests.list b/gfx/thebes/crashtests/crashtests.list index f98672428aca..6cee8f5f0447 100644 --- a/gfx/thebes/crashtests/crashtests.list +++ b/gfx/thebes/crashtests/crashtests.list @@ -9,6 +9,8 @@ load 333861-1.html load 334735-1.html load 345576-1.html load 345629-1.html +load 348462-1.html +load 348462-2.html load 369688-1.html load 369947-1.html load 372094-1.xhtml diff --git a/gfx/thebes/public/gfxASurface.h b/gfx/thebes/public/gfxASurface.h index 4c2143d646aa..c84f4ea14a60 100644 --- a/gfx/thebes/public/gfxASurface.h +++ b/gfx/thebes/public/gfxASurface.h @@ -40,6 +40,7 @@ #include "gfxTypes.h" #include "gfxRect.h" +#include "nsAutoPtr.h" typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_user_data_key cairo_user_data_key_t; diff --git a/gfx/thebes/public/gfxContext.h b/gfx/thebes/public/gfxContext.h index 23f2f068db8c..f9e95d2dfeb8 100644 --- a/gfx/thebes/public/gfxContext.h +++ b/gfx/thebes/public/gfxContext.h @@ -48,6 +48,7 @@ #include "gfxMatrix.h" #include "gfxPattern.h" #include "gfxPath.h" +#include "nsISupportsImpl.h" typedef struct _cairo cairo_t; @@ -66,7 +67,7 @@ typedef struct _cairo cairo_t; * as opposed to app units. */ class THEBES_API gfxContext { - THEBES_INLINE_DECL_REFCOUNTING(gfxContext) + NS_INLINE_DECL_REFCOUNTING(gfxContext) public: /** diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index 370654c53e02..f808c32ce9f6 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -55,6 +55,7 @@ #include "gfxFontConstants.h" #include "gfxPlatform.h" #include "nsIAtom.h" +#include "nsISupportsImpl.h" #ifdef DEBUG #include @@ -160,7 +161,7 @@ struct THEBES_API gfxFontStyle { class gfxFontEntry { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry) + NS_INLINE_DECL_REFCOUNTING(gfxFontEntry) gfxFontEntry(const nsAString& aName, gfxFontFamily *aFamily = nsnull, PRBool aIsStandardFace = PR_FALSE) : @@ -289,7 +290,7 @@ struct FontSearch { class gfxFontFamily { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontFamily) + NS_INLINE_DECL_REFCOUNTING(gfxFontFamily) gfxFontFamily(const nsAString& aName) : mName(aName), @@ -955,7 +956,7 @@ protected: }; class THEBES_API gfxTextRunFactory { - THEBES_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) + NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) public: // Flags in the mask 0xFFFF0000 are reserved for textrun clients diff --git a/gfx/thebes/public/gfxGdkNativeRenderer.h b/gfx/thebes/public/gfxGdkNativeRenderer.h index 68cf01570061..ca5bef4337aa 100644 --- a/gfx/thebes/public/gfxGdkNativeRenderer.h +++ b/gfx/thebes/public/gfxGdkNativeRenderer.h @@ -39,6 +39,7 @@ #define GFXGDKNATIVERENDER_H_ #include "gfxColor.h" +#include "nsAutoPtr.h" #include class gfxASurface; diff --git a/gfx/thebes/public/gfxPath.h b/gfx/thebes/public/gfxPath.h index 1a5cc2e9f729..127b81ea4d24 100644 --- a/gfx/thebes/public/gfxPath.h +++ b/gfx/thebes/public/gfxPath.h @@ -38,6 +38,7 @@ #define GFX_PATH_H #include "gfxTypes.h" +#include "nsISupportsImpl.h" class gfxContext; struct gfxPoint; @@ -48,7 +49,7 @@ typedef struct cairo_path cairo_path_t; * of a gfxContext. */ class THEBES_API gfxPath { - THEBES_INLINE_DECL_REFCOUNTING(gfxPath) + NS_INLINE_DECL_REFCOUNTING(gfxPath) friend class gfxContext; diff --git a/gfx/thebes/public/gfxPattern.h b/gfx/thebes/public/gfxPattern.h index 26f67b35f1d2..b378b815c02a 100644 --- a/gfx/thebes/public/gfxPattern.h +++ b/gfx/thebes/public/gfxPattern.h @@ -42,6 +42,8 @@ #include "gfxColor.h" #include "gfxMatrix.h" +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" class gfxContext; class gfxASurface; @@ -49,7 +51,7 @@ typedef struct _cairo_pattern cairo_pattern_t; class THEBES_API gfxPattern { - THEBES_INLINE_DECL_REFCOUNTING(gfxPattern) + NS_INLINE_DECL_REFCOUNTING(gfxPattern) public: gfxPattern(cairo_pattern_t *aPattern); diff --git a/gfx/thebes/public/gfxQtNativeRenderer.h b/gfx/thebes/public/gfxQtNativeRenderer.h index 9dd8de5482ad..57628d77854f 100644 --- a/gfx/thebes/public/gfxQtNativeRenderer.h +++ b/gfx/thebes/public/gfxQtNativeRenderer.h @@ -39,9 +39,8 @@ #define GFXQTNATIVERENDER_H_ #include "gfxColor.h" - -class gfxASurface; -class gfxContext; +#include "gfxASurface.h" +#include "gfxContext.h" class QWidget; class QRect; diff --git a/gfx/thebes/public/gfxRect.h b/gfx/thebes/public/gfxRect.h index c024211aa5bd..7da3e1f2678a 100644 --- a/gfx/thebes/public/gfxRect.h +++ b/gfx/thebes/public/gfxRect.h @@ -40,6 +40,7 @@ #include "gfxTypes.h" #include "gfxPoint.h" +#include "nsDebug.h" struct THEBES_API gfxCorner { typedef int Corner; diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index cb4dccebffa0..1e1f0862cb3d 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -90,36 +90,6 @@ enum gfxBreakPriority { eNormalBreak }; -/** - * Define refcounting for Thebes. For now use the stuff from nsISupportsImpl - * even though it forces the functions to be virtual... - */ -#include "nsISupportsImpl.h" -#include "nsAutoPtr.h" - -#define THEBES_INLINE_DECL_REFCOUNTING(_class) \ -public: \ - nsrefcnt AddRef(void) { \ - NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ - ++mRefCnt; \ - NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ - return mRefCnt; \ - } \ - nsrefcnt Release(void) { \ - NS_PRECONDITION(0 != mRefCnt, "dup release"); \ - --mRefCnt; \ - NS_LOG_RELEASE(this, mRefCnt, #_class); \ - if (mRefCnt == 0) { \ - mRefCnt = 1; /* stabilize */ \ - NS_DELETEXPCOM(this); \ - return 0; \ - } \ - return mRefCnt; \ - } \ -protected: \ - nsAutoRefCnt mRefCnt; \ -public: - #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ nsrefcnt AddRef(void) { \ diff --git a/gfx/thebes/public/gfxUserFontSet.h b/gfx/thebes/public/gfxUserFontSet.h index 654350c89d8a..aece55f5789b 100644 --- a/gfx/thebes/public/gfxUserFontSet.h +++ b/gfx/thebes/public/gfxUserFontSet.h @@ -46,6 +46,7 @@ #include "nsCOMPtr.h" #include "nsIURI.h" #include "nsIFile.h" +#include "nsISupportsImpl.h" class nsIURI; class gfxMixedFontFamily; @@ -138,7 +139,7 @@ class THEBES_API gfxUserFontSet { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxUserFontSet) + NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet) gfxUserFontSet(); virtual ~gfxUserFontSet(); diff --git a/gfx/thebes/src/gfxFontconfigUtils.h b/gfx/thebes/src/gfxFontconfigUtils.h index 7dcb6a38758b..4943f77b8cda 100644 --- a/gfx/thebes/src/gfxFontconfigUtils.h +++ b/gfx/thebes/src/gfxFontconfigUtils.h @@ -44,6 +44,7 @@ #include "nsAutoRef.h" #include "nsTArray.h" #include "nsTHashtable.h" +#include "nsISupportsImpl.h" #include @@ -87,7 +88,7 @@ class gfxIgnoreCaseCStringComparator class gfxFontNameList : public nsTArray { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontNameList) + NS_INLINE_DECL_REFCOUNTING(gfxFontNameList) PRBool Exists(nsAString& aName); }; diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index 3069a396e015..06b1da984218 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -935,7 +935,7 @@ GetFontGroup(PangoContext *aContext) class gfxFcPangoFontSet { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) + NS_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) explicit gfxFcPangoFontSet(FcPattern *aPattern, gfxUserFontSet *aUserFontSet) diff --git a/ipc/app/Makefile.in b/ipc/app/Makefile.in index 2992de99e77c..ada8f88474b1 100644 --- a/ipc/app/Makefile.in +++ b/ipc/app/Makefile.in @@ -92,6 +92,8 @@ OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 v OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32) endif +LIBS += $(JEMALLOC_LIBS) + include $(topsrcdir)/config/rules.mk ifeq ($(OS_ARCH),WINNT) diff --git a/js/ctypes/CTypes.cpp b/js/ctypes/CTypes.cpp index 91cc9d767bb0..0c846cec29f9 100644 --- a/js/ctypes/CTypes.cpp +++ b/js/ctypes/CTypes.cpp @@ -43,7 +43,7 @@ #include "nsUTF8Utils.h" #include "nsCRTGlue.h" #include "prlog.h" -#include "prdtoa.h" +#include "jsdtoa.h" #include #if defined(XP_WIN) || defined(XP_OS2) @@ -146,6 +146,8 @@ namespace FunctionType { static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); + static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval, + jsval* vp); } namespace CClosure { @@ -366,6 +368,7 @@ static JSPropertySpec sFunctionProps[] = { { "argTypes", 0, CTYPESPROP_FLAGS, FunctionType::ArgTypesGetter, NULL }, { "returnType", 0, CTYPESPROP_FLAGS, FunctionType::ReturnTypeGetter, NULL }, { "abi", 0, CTYPESPROP_FLAGS, FunctionType::ABIGetter, NULL }, + { "isVariadic", 0, CTYPESPROP_FLAGS, FunctionType::IsVariadicGetter, NULL }, { 0, 0, 0, NULL, NULL } }; @@ -2017,9 +2020,12 @@ BuildTypeName(JSContext* cx, JSObject* typeObj) for (PRUint32 i = 0; i < fninfo->mArgTypes.Length(); ++i) { JSString* argName = CType::GetName(cx, fninfo->mArgTypes[i]); result.Append(GetString(argName)); - if (i != fninfo->mArgTypes.Length() - 1) + if (i != fninfo->mArgTypes.Length() - 1 || + fninfo->mIsVariadic) result.Append(NS_LITERAL_STRING(", ")); } + if (fninfo->mIsVariadic) + result.Append(NS_LITERAL_STRING("...")); result.Append(')'); // Set 'currentType' to the return type, and let the loop process it. @@ -2110,9 +2116,12 @@ BuildTypeSource(JSContext* cx, JSObject* typeObj, bool makeShort) result.Append(NS_LITERAL_STRING(", [")); for (PRUint32 i = 0; i < fninfo->mArgTypes.Length(); ++i) { result.Append(BuildTypeSource(cx, fninfo->mArgTypes[i], true)); - if (i != fninfo->mArgTypes.Length() - 1) + if (i != fninfo->mArgTypes.Length() - 1 || + fninfo->mIsVariadic) result.Append(NS_LITERAL_STRING(", ")); } + if (fninfo->mIsVariadic) + result.Append(NS_LITERAL_STRING("\"...\"")); result.Append(']'); } @@ -2209,12 +2218,14 @@ BuildDataSource(JSContext* cx, JSObject* typeObj, void* data, bool isImplicit) #define DEFINE_FLOAT_TYPE(name, type, ffiType) \ case TYPE_##name: { \ /* Serialize as a primitive double. */ \ - PRFloat64 fp = *static_cast(data); \ - PRIntn decpt, sign; \ - char buf[128]; \ - PRStatus rv = PR_dtoa(fp, 0, 0, &decpt, &sign, NULL, buf, sizeof(buf)); \ - JS_ASSERT(rv == PR_SUCCESS); \ - result.AppendASCII(buf); \ + double fp = *static_cast(data); \ + char buf[DTOSTR_STANDARD_BUFFER_SIZE]; \ + char* str = JS_dtostr(buf, sizeof(buf), DTOSTR_STANDARD, 0, fp); \ + JS_ASSERT(str); \ + if (!str) \ + break; \ + \ + result.AppendASCII(str); \ break; \ } #define DEFINE_CHAR_TYPE(name, type, ffiType) \ @@ -2660,6 +2671,9 @@ CType::TypesEqual(JSContext* cx, JSObject* t1, JSObject* t2) if (f1->mArgTypes.Length() != f2->mArgTypes.Length()) return false; + if (f1->mIsVariadic != f2->mIsVariadic) + return false; + for (PRUint32 i = 0; i < f1->mArgTypes.Length(); ++i) { if (!TypesEqual(cx, f1->mArgTypes[i], f2->mArgTypes[i])) return false; @@ -4189,7 +4203,7 @@ struct AutoValue }; static bool -GetABI(JSContext* cx, jsval abiType, ffi_abi& result) +GetABI(JSContext* cx, jsval abiType, ffi_abi* result) { if (JSVAL_IS_PRIMITIVE(abiType)) return false; @@ -4201,11 +4215,11 @@ GetABI(JSContext* cx, jsval abiType, ffi_abi& result) // C calling convention (cdecl) on each platform. switch (abi) { case ABI_DEFAULT: - result = FFI_DEFAULT_ABI; + *result = FFI_DEFAULT_ABI; return true; case ABI_STDCALL: #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2) - result = FFI_STDCALL; + *result = FFI_STDCALL; return true; #endif case INVALID_ABI: @@ -4270,6 +4284,52 @@ PrepareReturnType(JSContext* cx, jsval type) return result; } +static JS_ALWAYS_INLINE bool +IsEllipsis(jsval v) +{ + if (!JSVAL_IS_STRING(v)) + return false; + JSString* str = JSVAL_TO_STRING(v); + if (JS_GetStringLength(str) != 3) + return false; + jschar* chars = JS_GetStringChars(str), dot('.'); + return (chars[0] == dot && + chars[1] == dot && + chars[2] == dot); +} + +static JSBool +PrepareCIF(JSContext* cx, + FunctionInfo* fninfo) +{ + ffi_abi abi; + if (!GetABI(cx, OBJECT_TO_JSVAL(fninfo->mABI), &abi)) { + JS_ReportError(cx, "Invalid ABI specification"); + return false; + } + + ffi_status status = + ffi_prep_cif(&fninfo->mCIF, + abi, + fninfo->mFFITypes.Length(), + CType::GetFFIType(cx, fninfo->mReturnType), + fninfo->mFFITypes.Elements()); + + switch (status) { + case FFI_OK: + return true; + case FFI_BAD_ABI: + JS_ReportError(cx, "Invalid ABI specification"); + return false; + case FFI_BAD_TYPEDEF: + JS_ReportError(cx, "Invalid type specification"); + return false; + default: + JS_ReportError(cx, "Unknown libffi error"); + return false; + } +} + static FunctionInfo* NewFunctionInfo(JSContext* cx, jsval abiType, @@ -4283,19 +4343,12 @@ NewFunctionInfo(JSContext* cx, return NULL; } - // determine the ABI - ffi_abi abi; - if (!GetABI(cx, abiType, abi)) { - JS_ReportError(cx, "Invalid ABI specification"); - return NULL; - } fninfo->mABI = JSVAL_TO_OBJECT(abiType); // prepare the result type fninfo->mReturnType = PrepareReturnType(cx, returnType); if (!fninfo->mReturnType) return NULL; - ffi_type* rtype = CType::GetFFIType(cx, fninfo->mReturnType); // prepare the argument types if (!fninfo->mArgTypes.SetCapacity(argLength) || @@ -4304,7 +4357,29 @@ NewFunctionInfo(JSContext* cx, return NULL; } + fninfo->mIsVariadic = false; + for (PRUint32 i = 0; i < argLength; ++i) { + if (IsEllipsis(argTypes[i])) { + fninfo->mIsVariadic = true; + if (i < 1) { + JS_ReportError(cx, "\"...\" may not be the first and only parameter " + "type of a variadic function declaration"); + return NULL; + } + if (i < argLength - 1) { + JS_ReportError(cx, "\"...\" must be the last parameter type of a " + "variadic function declaration"); + return NULL; + } + if (GetABICode(cx, fninfo->mABI) != ABI_DEFAULT) { + JS_ReportError(cx, "Variadic functions must use the __cdecl calling " + "convention"); + return NULL; + } + break; + } + JSObject* argType = PrepareType(cx, argTypes[i]); if (!argType) return NULL; @@ -4313,21 +4388,14 @@ NewFunctionInfo(JSContext* cx, fninfo->mFFITypes.AppendElement(CType::GetFFIType(cx, argType)); } - ffi_status status = ffi_prep_cif(&fninfo->mCIF, abi, - fninfo->mFFITypes.Length(), rtype, fninfo->mFFITypes.Elements()); - switch (status) { - case FFI_OK: + if (fninfo->mIsVariadic) + // wait to PrepareCIF until function is called return fninfo.forget(); - case FFI_BAD_ABI: - JS_ReportError(cx, "Invalid ABI specification"); + + if (!PrepareCIF(cx, fninfo)) return NULL; - case FFI_BAD_TYPEDEF: - JS_ReportError(cx, "Invalid type specification"); - return NULL; - default: - JS_ReportError(cx, "Unknown libffi error"); - return NULL; - } + + return fninfo.forget(); } JSBool @@ -4453,6 +4521,11 @@ FunctionType::ConstructData(JSContext* cx, PRFuncPtr* data = static_cast(CData::GetData(cx, result)); if (JSVAL_IS_OBJECT(arg) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(arg))) { + FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, obj); + if (fninfo->mIsVariadic) { + JS_ReportError(cx, "Can't declare a variadic callback function"); + return JS_FALSE; + } // Construct from a JS function, and allow an optional 'this' argument. JSObject* thisObj = NULL; if (argc == 2) { @@ -4493,6 +4566,35 @@ FunctionType::ConstructData(JSContext* cx, return JS_FALSE; } +typedef nsAutoTArray AutoValueAutoArray; + +static JSBool +ConvertArgument(JSContext* cx, + jsval arg, + JSObject* type, + AutoValueAutoArray* values, + AutoValueAutoArray* strings) +{ + AutoValue* value = values->AppendElement(); + + if (!value->SizeToType(cx, type)) { + JS_ReportAllocationOverflow(cx); + return false; + } + + bool freePointer = false; + if (!ImplicitConvert(cx, arg, type, value->mData, true, &freePointer)) + return false; + + if (freePointer) { + // ImplicitConvert converted a string for us, which we have to free. + // Keep track of it. + strings->AppendElement()->mData = *static_cast(value->mData); + } + + return true; +} + JSBool FunctionType::Call(JSContext* cx, JSObject* obj, @@ -4514,8 +4616,10 @@ FunctionType::Call(JSContext* cx, } FunctionInfo* fninfo = GetFunctionInfo(cx, typeObj); + PRUint32 argcFixed = fninfo->mArgTypes.Length(); - if (argc != fninfo->mArgTypes.Length()) { + if ((!fninfo->mIsVariadic && argc != argcFixed) || + (fninfo->mIsVariadic && argc < argcFixed)) { JS_ReportError(cx, "Number of arguments does not match declaration"); return false; } @@ -4532,25 +4636,41 @@ FunctionType::Call(JSContext* cx, } // prepare the values for each argument - nsAutoTArray values; - nsAutoTArray strings; - for (PRUint32 i = 0; i < fninfo->mArgTypes.Length(); ++i) { - AutoValue* value = values.AppendElement(); - bool freePointer = false; - if (!value->SizeToType(cx, fninfo->mArgTypes[i])) { - JS_ReportAllocationOverflow(cx); - return false; - } + AutoValueAutoArray values; + AutoValueAutoArray strings; - if (!ImplicitConvert(cx, argv[i], fninfo->mArgTypes[i], value->mData, true, - &freePointer)) + for (PRUint32 i = 0; i < argcFixed; ++i) + if (!ConvertArgument(cx, argv[i], fninfo->mArgTypes[i], &values, &strings)) return false; - if (freePointer) { - // ImplicitConvert converted a string for us, which we have to free. - // Keep track of it. - strings.AppendElement()->mData = *static_cast(value->mData); + if (fninfo->mIsVariadic) { + fninfo->mFFITypes.SetLength(argcFixed); + ASSERT_OK(fninfo->mFFITypes.SetCapacity(argc)); + + JSObject* obj; // Could reuse obj instead of declaring a second + JSObject* type; // JSObject*, but readability would suffer. + + for (PRUint32 i = argcFixed; i < argc; ++i) { + if (JSVAL_IS_PRIMITIVE(argv[i]) || + !CData::IsCData(cx, obj = JSVAL_TO_OBJECT(argv[i]))) { + // Since we know nothing about the CTypes of the ... arguments, + // they absolutely must be CData objects already. + JS_ReportError(cx, "argument %d of type %s is not a CData object", + i, JS_GetTypeName(cx, JS_TypeOfValue(cx, argv[i]))); + return false; + } + if (!(type = CData::GetCType(cx, obj)) || + !(type = PrepareType(cx, OBJECT_TO_JSVAL(type))) || + // Relying on ImplicitConvert only for the limited purpose of + // converting one CType to another (e.g., T[] to T*). + !ConvertArgument(cx, argv[i], type, &values, &strings)) { + // These functions report their own errors. + return false; + } + fninfo->mFFITypes.AppendElement(CType::GetFFIType(cx, type)); } + if (!PrepareCIF(cx, fninfo)) + return false; } // initialize a pointer to an appropriate location, for storing the result @@ -4590,13 +4710,21 @@ FunctionType::GetFunctionInfo(JSContext* cx, JSObject* obj) return static_cast(JSVAL_TO_PRIVATE(slot)); } -JSBool -FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) +static JSBool +CheckFunctionType(JSContext* cx, JSObject* obj) { if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) { JS_ReportError(cx, "not a FunctionType"); return JS_FALSE; } + return JS_TRUE; +} + +JSBool +FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) +{ + if (!CheckFunctionType(cx, obj)) + return JS_FALSE; // Check if we have a cached argTypes array. ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ARGS_T, vp)); @@ -4630,10 +4758,8 @@ FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v JSBool FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) { - if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) { - JS_ReportError(cx, "not a FunctionType"); + if (!CheckFunctionType(cx, obj)) return JS_FALSE; - } // Get the returnType object from the FunctionInfo. *vp = OBJECT_TO_JSVAL(GetFunctionInfo(cx, obj)->mReturnType); @@ -4643,16 +4769,24 @@ FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* JSBool FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) { - if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) { - JS_ReportError(cx, "not a FunctionType"); + if (!CheckFunctionType(cx, obj)) return JS_FALSE; - } // Get the abi object from the FunctionInfo. *vp = OBJECT_TO_JSVAL(GetFunctionInfo(cx, obj)->mABI); return JS_TRUE; } +JSBool +FunctionType::IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) +{ + if (!CheckFunctionType(cx, obj)) + return JS_FALSE; + + *vp = BOOLEAN_TO_JSVAL(GetFunctionInfo(cx, obj)->mIsVariadic); + return JS_TRUE; +} + /******************************************************************************* ** CClosure implementation *******************************************************************************/ @@ -4671,6 +4805,7 @@ CClosure::Create(JSContext* cx, // Get the FunctionInfo from the FunctionType. FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj); + JS_ASSERT(!fninfo->mIsVariadic); nsAutoPtr cinfo(new ClosureInfo()); if (!cinfo) { diff --git a/js/ctypes/CTypes.h b/js/ctypes/CTypes.h index e6fc2417f2c9..7215b56514cf 100644 --- a/js/ctypes/CTypes.h +++ b/js/ctypes/CTypes.h @@ -104,14 +104,34 @@ struct PropertySpec JSPropertyOp setter; }; -// Descriptor of ABI, return type, and argument types for a FunctionType. +// Descriptor of ABI, return type, argument types, and variadicity for a +// FunctionType. struct FunctionInfo { + // Initialized in NewFunctionInfo when !mIsVariadic, but only later, in + // FunctionType::Call, when mIsVariadic. Not always consistent with + // mFFITypes, due to lazy initialization when mIsVariadic. ffi_cif mCIF; - JSObject* mABI; + + // Calling convention of the function. Convert to ffi_abi using GetABI + // and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing. + JSObject* mABI; + + // The CType of the value returned by the function. JSObject* mReturnType; - nsTArray mArgTypes; + + // A fixed array of known parameter types, excluding any variadic + // parameters (if mIsVariadic). + nsTArray mArgTypes; + + // A variable array of ffi_type*s corresponding to both known parameter + // types and dynamic (variadic) parameter types. Longer than mArgTypes + // only if mIsVariadic. nsTArray mFFITypes; + + // Flag indicating whether the function behaves like a C function with + // ... as the final formal parameter. + bool mIsVariadic; }; // Parameters necessary for invoking a JS function from a C closure. diff --git a/js/ctypes/ctypes.jsm b/js/ctypes/ctypes.jsm index 285c91dfa5e1..d6e82db9780c 100644 --- a/js/ctypes/ctypes.jsm +++ b/js/ctypes/ctypes.jsm @@ -94,7 +94,8 @@ let EXPORTED_SYMBOLS = [ "ctypes" ]; * @returnType The return type of the function. Must be a type constant * from ctypes. * @argTypes Argument types. Must be a type constant (other than void_t) - * from ctypes. + * from ctypes, or the literal string "..." to denote a + * variadic function. * @returns A function object. * * A function object can then be used to call the C function it represents @@ -108,7 +109,9 @@ let EXPORTED_SYMBOLS = [ "ctypes" ]; * Arguments will be checked against the types supplied at declaration, and * some attempt to convert values (e.g. boolean true/false to integer 0/1) * will be made. Otherwise, if types do not match, or conversion fails, - * an exception will be thrown. + * an exception will be thrown. Arguments passed as variadic parameters + * must have an explicit ctypes type, since their types are not declared + * in the signature. */ // Initialize the ctypes object. You do not need to do this yourself. diff --git a/js/ctypes/tests/jsctypes-test.cpp b/js/ctypes/tests/jsctypes-test.cpp index 52f5d6d4ae1d..63d1032b9593 100644 --- a/js/ctypes/tests/jsctypes-test.cpp +++ b/js/ctypes/tests/jsctypes-test.cpp @@ -42,6 +42,7 @@ #include "nsCRTGlue.h" #include #include +#include void test_void_t_cdecl() @@ -334,3 +335,67 @@ test_closure_cdecl(PRInt8 i, PRInt32 (NS_STDCALL *f)(PRInt8)) } #endif /* defined(_WIN32) && !defined(__WIN64) */ +template struct PromotedTraits { + typedef T type; +}; +#define DECL_PROMOTED(FROM, TO) \ + template <> struct PromotedTraits { \ + typedef TO type; \ + } +DECL_PROMOTED(bool, int); +DECL_PROMOTED(char, int); +DECL_PROMOTED(short, int); + +PRInt32 +test_sum_va_cdecl(PRUint8 n, ...) +{ + va_list list; + PRInt32 sum = 0; + va_start(list, n); + for (PRUint8 i = 0; i < n; ++i) + sum += va_arg(list, PromotedTraits::type); + va_end(list); + return sum; +} + +PRUint8 +test_count_true_va_cdecl(PRUint8 n, ...) +{ + va_list list; + PRUint8 count = 0; + va_start(list, n); + for (PRUint8 i = 0; i < n; ++i) + if (va_arg(list, PromotedTraits::type)) + count += 1; + va_end(list); + return count; +} + +void +test_add_char_short_int_va_cdecl(PRUint32* result, ...) +{ + va_list list; + va_start(list, result); + *result += va_arg(list, PromotedTraits::type); + *result += va_arg(list, PromotedTraits::type); + *result += va_arg(list, PromotedTraits::type); + va_end(list); +} + +PRInt32* +test_vector_add_va_cdecl(PRUint8 num_vecs, + PRUint8 vec_len, + PRInt32* result, ...) +{ + va_list list; + va_start(list, result); + PRUint8 i; + for (i = 0; i < vec_len; ++i) + result[i] = 0; + for (i = 0; i < num_vecs; ++i) { + PRInt32* vec = va_arg(list, PRInt32*); + for (PRUint8 j = 0; j < vec_len; ++j) + result[j] += vec[j]; + } + return result; +} diff --git a/js/ctypes/tests/jsctypes-test.h b/js/ctypes/tests/jsctypes-test.h index b3ad8c4f986f..1ba322fa1b7a 100644 --- a/js/ctypes/tests/jsctypes-test.h +++ b/js/ctypes/tests/jsctypes-test.h @@ -195,5 +195,11 @@ NS_EXTERN_C NS_EXPORT PRInt32 test_callme(PRInt8); NS_EXPORT void* test_getfn(); -} + EXPORT_CDECL(PRInt32) test_sum_va_cdecl(PRUint8 n, ...); + EXPORT_CDECL(PRUint8) test_count_true_va_cdecl(PRUint8 n, ...); + EXPORT_CDECL(void) test_add_char_short_int_va_cdecl(PRUint32* result, ...); + EXPORT_CDECL(PRInt32*) test_vector_add_va_cdecl(PRUint8 num_vecs, + PRUint8 vec_len, + PRInt32* result, ...); +} diff --git a/js/ctypes/tests/unit/test_jsctypes.js.in b/js/ctypes/tests/unit/test_jsctypes.js.in index ed08e057678b..19d799ecb94b 100644 --- a/js/ctypes/tests/unit/test_jsctypes.js.in +++ b/js/ctypes/tests/unit/test_jsctypes.js.in @@ -53,8 +53,10 @@ function do_check_throws(f, type, stack) try { f(); } catch (exc) { - if (exc instanceof type) + if (exc instanceof type) { + do_check_true(true); return; + } do_throw("expected " + type.name + " exception, caught " + exc, stack); } do_throw("expected " + type.name + " exception, none thrown", stack); @@ -189,6 +191,7 @@ function run_test() run_struct_tests(library); run_function_tests(library); run_closure_tests(library); + run_variadic_tests(library); // test the string version of ctypes.open() as well let libpath = libfile.path; @@ -950,6 +953,19 @@ function run_float_tests(library, t, name, size) { for (let i = 0; i < vals.length; i++) do_check_throws(function () { d.value = vals[i]; }, TypeError); + // Check that values roundtrip through toSource() correctly. + function test_roundtrip(t, val) + { + let f1 = t(val); + eval("let f2 = " + f1.toSource()); + do_check_eq(f1.value, f2.value); + } + let vals = [Infinity, -Infinity, -0, 0, 1, -1, 1/3, -1/3, 1/4, -1/4, + 1e-14, -1e-14, 0xfffffffffffff000, -0xfffffffffffff000]; + for (let i = 0; i < vals.length; i++) + test_roundtrip(t, vals[i]); + do_check_eq(t(NaN).toSource(), t.toSource() + "(NaN)"); + do_check_true(d.address().constructor === t.ptr); do_check_eq(d.address().contents, d.value); do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value + ")"); @@ -1663,7 +1679,8 @@ function run_FunctionType_tests() { run_type_ctor_class_tests(ctypes.FunctionType, ctypes.FunctionType(ctypes.default_abi, ctypes.void_t), ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.int32_t ]), - [ "abi", "returnType", "argTypes" ], undefined, undefined, undefined, undefined); + [ "abi", "returnType", "argTypes", "isVariadic" ], + undefined, undefined, undefined, undefined); do_check_throws(function() { ctypes.FunctionType(); }, Error); do_check_throws(function() { @@ -2111,6 +2128,94 @@ function run_single_closure_tests(library, abi, suffix) do_check_eq(test_closure(-52, closure2), -52 + thisobj.a); } +function run_variadic_tests(library) { + let sum_va_type = ctypes.FunctionType(ctypes.default_abi, + ctypes.int32_t, + [ctypes.uint8_t, "..."]), + sum_va = library.declare("test_sum_va_cdecl", ctypes.default_abi, ctypes.int32_t, + ctypes.uint8_t, "..."); + + do_check_eq(sum_va_type.toSource(), + 'ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.uint8_t, "..."])'); + do_check_eq(sum_va.constructor.name, "int32_t(*)(uint8_t, ...)"); + do_check_true(sum_va.constructor.isVariadic); + + do_check_eq(sum_va(3, + ctypes.int32_t(1), + ctypes.int32_t(2), + ctypes.int32_t(3)), + 6); + + do_check_throws(function() { + ctypes.FunctionType(ctypes.default_abi, ctypes.bool, + [ctypes.bool, "...", ctypes.bool]); + }, Error); + + do_check_throws(function() { + ctypes.FunctionType(ctypes.default_abi, ctypes.bool, ["..."]); + }, Error); + +#ifdef _WIN32 +#ifndef _WIN64 + do_check_throws(function() { + ctypes.FunctionType(ctypes.stdcall_abi, ctypes.bool, + [ctypes.bool, "..."]); + }, Error); +#endif +#endif + + do_check_throws(function() { + // No variadic closure callbacks allowed. + sum_va_type(function(){}); + }, Error); + + let count_true_va = library.declare("test_sum_va_cdecl", ctypes.default_abi, ctypes.uint8_t, + ctypes.uint8_t, "..."); + do_check_eq(count_true_va(8, + ctypes.bool(false), + ctypes.bool(false), + ctypes.bool(false), + ctypes.bool(true), + ctypes.bool(true), + ctypes.bool(false), + ctypes.bool(true), + ctypes.bool(true)), + 4); + + let add_char_short_int_va = library.declare("test_add_char_short_int_va_cdecl", + ctypes.default_abi, ctypes.void_t, + ctypes.uint32_t.ptr, "..."), + result = ctypes.uint32_t(3); + + add_char_short_int_va(result.address(), + ctypes.char(5), + ctypes.short(7), + ctypes.uint32_t(11)); + + do_check_eq(result.value, 3 + 5 + 7 + 11); + + let result = ctypes.int32_t.array(3)([1,1,1]), + v1 = ctypes.int32_t.array(4)([1,2,3,5]), + v2 = ctypes.int32_t.array(3)([7,11,13]), + vector_add_va = library.declare("test_vector_add_va_cdecl", + ctypes.default_abi, ctypes.int32_t.ptr, + ctypes.uint8_t, ctypes.uint8_t, "..."), + // Note that vector_add_va zeroes out result first. + vec_sum = vector_add_va(2, 3, result, v1, v2); + do_check_eq(vec_sum.contents, 8); + do_check_eq(result[0], 8); + do_check_eq(result[1], 13); + do_check_eq(result[2], 16); + + do_check_true(!!(sum_va_type().value = sum_va_type())); + let sum_notva_type = ctypes.FunctionType(sum_va_type.abi, + sum_va_type.returnType, + [ctypes.uint8_t]); + do_check_throws(function() { + sum_va_type().value = sum_notva_type(); + }, Error); +} + // bug 522360 - try loading system library without full path function run_load_system_library() { diff --git a/layout/base/crashtests/538082-1.xul b/layout/base/crashtests/538082-1.xul new file mode 100644 index 000000000000..10335617eab9 --- /dev/null +++ b/layout/base/crashtests/538082-1.xul @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index cd45ba3b1e0e..c2a06f40f862 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -73,6 +73,7 @@ load 325967-1.html load 325984-1.xhtml load 325984-2.html load 328944-1.xul +load 329900-1.html load 330015-1.html load 331204-1.html load 331679-1.xhtml @@ -279,5 +280,6 @@ load 536623-1.xhtml load 537059-1.xhtml load 537141-1.xhtml load 537562-1.xhtml +load 538082-1.xul load 541869-1.xhtml load 541869-2.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 9618daf3dac2..749705520b15 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -422,7 +422,7 @@ ReparentFrame(nsFrameManager* aFrameManager, nsIFrame* aFrame) { aFrame->SetParent(aNewParentFrame); - aFrameManager->ReParentStyleContext(aFrame); + aFrameManager->ReparentStyleContext(aFrame); if (aFrame->GetStateBits() & (NS_FRAME_HAS_VIEW | NS_FRAME_HAS_CHILD_WITH_VIEW)) { // No need to walk up the tree, since the bits are already set @@ -7645,7 +7645,7 @@ nsCSSFrameConstructor::DoContentStateChanged(nsIContent* aContent, } } - nsReStyleHint rshint = + nsRestyleHint rshint = styleSet->HasStateDependentStyle(presContext, aContent, aStateMask); if ((aStateMask & NS_EVENT_STATE_HOVER) && rshint != 0) { @@ -7662,7 +7662,7 @@ nsCSSFrameConstructor::AttributeWillChange(nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType) { - nsReStyleHint rshint = + nsRestyleHint rshint = mPresShell->FrameManager()->HasAttributeDependentStyle(aContent, aAttribute, aModType, @@ -7749,7 +7749,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIContent* aContent, // See if we can optimize away the style re-resolution -- must be called after // the frame's AttributeChanged() in case it does something that affects the style nsFrameManager *frameManager = shell->FrameManager(); - nsReStyleHint rshint = frameManager->HasAttributeDependentStyle(aContent, + nsRestyleHint rshint = frameManager->HasAttributeDependentStyle(aContent, aAttribute, aModType, PR_TRUE); @@ -8601,7 +8601,7 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, // ContentRemoved triggered reconstruction, then we don't need to do this // because the frames will already have been built. if (aAsyncInsert) { - PostRestyleEvent(aContent, nsReStyleHint(0), nsChangeHint_ReconstructFrame); + PostRestyleEvent(aContent, nsRestyleHint(0), nsChangeHint_ReconstructFrame); } else { rv = ContentInserted(container, aContent, indexInContainer, mTempFrameTreeState); @@ -10797,7 +10797,7 @@ nsCSSFrameConstructor::RestyleForAppend(nsIContent* aContainer, return; if (selectorFlags & NODE_HAS_SLOW_SELECTOR) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10817,7 +10817,7 @@ nsCSSFrameConstructor::RestyleForAppend(nsIContent* aContainer, } } if (wasEmpty) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10827,7 +10827,7 @@ nsCSSFrameConstructor::RestyleForAppend(nsIContent* aContainer, for (PRInt32 index = aNewIndexInContainer - 1; index >= 0; --index) { nsIContent *content = aContainer->GetChildAt(index); if (content->IsNodeOfType(nsINode::eELEMENT)) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); break; } } @@ -10853,7 +10853,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, if (selectorFlags & (NODE_HAS_SLOW_SELECTOR | NODE_HAS_SLOW_SELECTOR_NOAPPEND)) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10877,7 +10877,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, } } if (wasEmpty) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10896,7 +10896,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, } if (content->IsNodeOfType(nsINode::eELEMENT)) { if (passedChild) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -10912,7 +10912,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, } if (content->IsNodeOfType(nsINode::eELEMENT)) { if (passedChild) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -10934,7 +10934,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, if (selectorFlags & (NODE_HAS_SLOW_SELECTOR | NODE_HAS_SLOW_SELECTOR_NOAPPEND)) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10956,7 +10956,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, } } if (isEmpty) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10970,7 +10970,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, break; // went through all children if (content->IsNodeOfType(nsINode::eELEMENT)) { if (index >= aIndexInContainer) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -10981,7 +10981,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, nsIContent *content = aContainer->GetChildAt(index); if (content->IsNodeOfType(nsINode::eELEMENT)) { if (index < aIndexInContainer) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -11012,7 +11012,7 @@ CollectRestyles(nsISupports* aContent, void nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, - nsReStyleHint aRestyleHint, + nsRestyleHint aRestyleHint, nsChangeHint aChangeHint) { NS_PRECONDITION(aContent, "Must have content node"); @@ -11025,7 +11025,7 @@ nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, } nsIFrame* primaryFrame = aContent->GetPrimaryFrame(); - if (aRestyleHint & eReStyle_Self) { + if (aRestyleHint & eRestyle_Self) { RestyleElement(aContent, primaryFrame, aChangeHint); } else if (aChangeHint && (primaryFrame || @@ -11036,7 +11036,7 @@ nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, ProcessRestyledFrames(changeList); } - if (aRestyleHint & eReStyle_LaterSiblings) { + if (aRestyleHint & eRestyle_LaterSiblings) { RestyleLaterSiblings(aContent); } } @@ -11141,6 +11141,10 @@ nsCSSFrameConstructor::ProcessPendingRestyleTable( count = aRestyles.Count(); } + // Set mInStyleRefresh to false now, since the EndUpdate call might + // add more restyles. + mInStyleRefresh = PR_FALSE; + EndUpdate(); #ifdef DEBUG @@ -11163,8 +11167,9 @@ nsCSSFrameConstructor::ProcessPendingRestyles() ProcessPendingRestyleTable(mPendingRestyles); - NS_POSTCONDITION(mPendingRestyles.Count() == 0, - "We should have processed mPendingRestyles to completion"); +#ifdef DEBUG + PRUint32 oldPendingRestyleCount = mPendingRestyles.Count(); +#endif // ...and then process animation restyles. This needs to happen // second because we need to start animations that resulted from the @@ -11179,12 +11184,7 @@ nsCSSFrameConstructor::ProcessPendingRestyles() presContext->SetProcessingAnimationStyleChange(PR_FALSE); presContext->SetProcessingRestyles(PR_FALSE); - mInStyleRefresh = PR_FALSE; - - NS_POSTCONDITION(mPendingAnimationRestyles.Count() == 0, - "We should have processed mPendingAnimationRestyles to " - "completion"); - NS_POSTCONDITION(mPendingRestyles.Count() == 0, + NS_POSTCONDITION(mPendingRestyles.Count() == oldPendingRestyleCount, "We should not have posted new non-animation restyles while " "processing animation restyles"); @@ -11198,7 +11198,7 @@ nsCSSFrameConstructor::ProcessPendingRestyles() void nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent, - nsReStyleHint aRestyleHint, + nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint, PRBool aForAnimation) { @@ -11215,7 +11215,7 @@ nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent, "Shouldn't be trying to restyle non-elements directly"); RestyleData existingData; - existingData.mRestyleHint = nsReStyleHint(0); + existingData.mRestyleHint = nsRestyleHint(0); existingData.mChangeHint = NS_STYLE_HINT_NONE; nsDataHashtable &restyles = @@ -11223,7 +11223,7 @@ nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent, restyles.Get(aContent, &existingData); existingData.mRestyleHint = - nsReStyleHint(existingData.mRestyleHint | aRestyleHint); + nsRestyleHint(existingData.mRestyleHint | aRestyleHint); NS_UpdateHint(existingData.mChangeHint, aMinChangeHint); restyles.Put(aContent, existingData); diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 989e3e0821d5..a44b47b9376e 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -193,7 +193,7 @@ private: // This function does not call ProcessAttachedQueue() on the binding manager. // If the caller wants that to happen synchronously, it needs to handle that // itself. - void ProcessOneRestyle(nsIContent* aContent, nsReStyleHint aRestyleHint, + void ProcessOneRestyle(nsIContent* aContent, nsRestyleHint aRestyleHint, nsChangeHint aChangeHint); void ProcessPendingRestyleTable( @@ -229,7 +229,7 @@ public: void RebuildAllStyleData(nsChangeHint aExtraHint); // See PostRestyleEventCommon below. - void PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint, + void PostRestyleEvent(nsIContent* aContent, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { nsPresContext *presContext = mPresShell->GetPresContext(); @@ -241,7 +241,7 @@ public: // See PostRestyleEventCommon below. void PostAnimationRestyleEvent(nsIContent* aContent, - nsReStyleHint aRestyleHint, + nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { PostRestyleEventCommon(aContent, aRestyleHint, aMinChangeHint, PR_TRUE); @@ -265,7 +265,7 @@ private: * IsProcessingAnimationStyleChange() value * (which is the default value). */ - void PostRestyleEventCommon(nsIContent* aContent, nsReStyleHint aRestyleHint, + void PostRestyleEventCommon(nsIContent* aContent, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint, PRBool aForAnimation); void PostRestyleEventInternal(); @@ -1698,7 +1698,7 @@ private: public: struct RestyleData { - nsReStyleHint mRestyleHint; // What we want to restyle + nsRestyleHint mRestyleHint; // What we want to restyle nsChangeHint mChangeHint; // The minimal change hint for "self" }; diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index a40b20788f6f..1bda957fbf8a 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -497,7 +497,7 @@ nsresult nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) return rv; } -nsIFrame * nsCaret::GetCaretFrame() +nsIFrame * nsCaret::GetCaretFrame(PRInt32 *aOffset) { // Return null if we're not drawn to prevent anybody from trying to draw us. if (!mDrawn) @@ -505,14 +505,17 @@ nsIFrame * nsCaret::GetCaretFrame() // Recompute the frame that we're supposed to draw in to guarantee that // we're not going to try to draw into a stale (dead) frame. - PRInt32 unused; + PRInt32 offset; nsIFrame *frame = nsnull; nsresult rv = GetCaretFrameForNodeOffset(mLastContent, mLastContentOffset, mLastHint, mLastBidiLevel, &frame, - &unused); + &offset); if (NS_FAILED(rv)) return nsnull; + if (aOffset) { + *aOffset = offset; + } return frame; } @@ -545,7 +548,10 @@ void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, NS_ASSERTION(mDrawn, "The caret shouldn't be drawing"); const nsRect drawCaretRect = mCaretRect + aOffset; - nscolor cssColor = aForFrame->GetStyleColor()->mColor; + PRInt32 contentOffset; + nsIFrame* frame = GetCaretFrame(&contentOffset); + NS_ASSERTION(frame == aForFrame, "We're referring different frame"); + nscolor foregroundColor = aForFrame->GetCaretColorAt(contentOffset); // Only draw the native caret if the foreground color matches that of // -moz-fieldtext (the color of the text in a textbox). If it doesn't match @@ -559,7 +565,7 @@ void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, nsILookAndFeel* lookAndFeel = presContext->LookAndFeel(); nscolor fieldText; if (NS_SUCCEEDED(lookAndFeel->GetColor(nsILookAndFeel::eColor__moz_fieldtext, fieldText)) && - fieldText == cssColor) { + fieldText == foregroundColor) { theme->DrawWidgetBackground(aCtx, aForFrame, NS_THEME_TEXTFIELD_CARET, drawCaretRect, drawCaretRect); return; @@ -567,7 +573,7 @@ void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, } } - aCtx->SetColor(cssColor); + aCtx->SetColor(foregroundColor); aCtx->FillRect(drawCaretRect); if (!GetHookRect().IsEmpty()) aCtx->FillRect(GetHookRect() + aOffset); diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index dc74d1d9689e..74346d819861 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -136,8 +136,10 @@ class nsCaret : public nsISelectionListener * Get the current frame that the caret should be drawn in. If the caret is * not currently visible (i.e., it is between blinks), then this will * return null. + * + * @param aOffset is result of the caret offset in the content. */ - nsIFrame* GetCaretFrame(); + nsIFrame* GetCaretFrame(PRInt32 *aOffset = nsnull); /** GetCaretRect * Get the current caret rect. Only call this when GetCaretFrame returns diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index b6a22179d176..6677c7a61105 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -139,13 +139,13 @@ inline PRBool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) { nsChangeHint(NS_STYLE_HINT_REFLOW | nsChangeHint_ReconstructFrame) /** - * |nsReStyleHint| is a bitfield for the result of |HasStateDependentStyle| + * |nsRestyleHint| is a bitfield for the result of |HasStateDependentStyle| * and |HasAttributeDependentStyle|. All values have an implied "and - * descendants." When no restyling is necessary, use |nsReStyleHint(0)|. + * descendants." When no restyling is necessary, use |nsRestyleHint(0)|. */ -enum nsReStyleHint { - eReStyle_Self = 0x1, - eReStyle_LaterSiblings = 0x2 +enum nsRestyleHint { + eRestyle_Self = 0x1, + eRestyle_LaterSiblings = 0x2 }; diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e7a6e43a4b48..48e588935e08 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -974,12 +974,13 @@ static PRBool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, static PRBool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, void* aClosure) { // These GetUnderlyingFrame calls return non-null because we're only used - // in sorting - PRInt32 diff = nsLayoutUtils::GetZIndex(aItem1->GetUnderlyingFrame()) - - nsLayoutUtils::GetZIndex(aItem2->GetUnderlyingFrame()); - if (diff == 0) + // in sorting. Note that we can't just take the difference of the two + // z-indices here, because that might overflow a 32-bit int. + PRInt32 index1 = nsLayoutUtils::GetZIndex(aItem1->GetUnderlyingFrame()); + PRInt32 index2 = nsLayoutUtils::GetZIndex(aItem2->GetUnderlyingFrame()); + if (index1 == index2) return IsContentLEQ(aItem1, aItem2, aClosure); - return diff < 0; + return index1 < index2; } void nsDisplayList::ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder) { diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index d89399ae2189..c5c566deea07 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -757,7 +757,7 @@ TryStartingTransition(nsPresContext *aPresContext, nsIContent *aContent, } nsresult -nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) +nsFrameManager::ReparentStyleContext(nsIFrame* aFrame) { if (nsGkAtoms::placeholderFrame == aFrame->GetType()) { // Also reparent the out-of-flow @@ -765,7 +765,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame); NS_ASSERTION(outOfFlow, "no out-of-flow frame"); - ReParentStyleContext(outOfFlow); + ReparentStyleContext(outOfFlow); } // DO NOT verify the style tree before reparenting. The frame @@ -773,16 +773,15 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) nsStyleContext* oldContext = aFrame->GetStyleContext(); // XXXbz can oldContext really ever be null? if (oldContext) { - nsPresContext *presContext = GetPresContext(); nsRefPtr newContext; nsIFrame* providerFrame = nsnull; PRBool providerIsChild = PR_FALSE; nsIFrame* providerChild = nsnull; - aFrame->GetParentStyleContextFrame(presContext, &providerFrame, + aFrame->GetParentStyleContextFrame(GetPresContext(), &providerFrame, &providerIsChild); nsStyleContext* newParentContext = nsnull; if (providerIsChild) { - ReParentStyleContext(providerFrame); + ReparentStyleContext(providerFrame); newParentContext = providerFrame->GetStyleContext(); providerChild = providerFrame; } else if (providerFrame) { @@ -835,20 +834,20 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) // continuation). newContext = prevContinuationContext; } else { - newContext = mStyleSet->ReParentStyleContext(presContext, oldContext, + newContext = mStyleSet->ReparentStyleContext(oldContext, newParentContext); } if (newContext) { if (newContext != oldContext) { // We probably don't want to initiate transitions from - // ReParentStyleContext, since we call it during frame + // ReparentStyleContext, since we call it during frame // construction rather than in response to dynamic changes. // Also see the comment at the start of // nsTransitionManager::ConsiderStartingTransition. #if 0 if (!copyFromContinuation) { - TryStartingTransition(presContext, aFrame->GetContent(), + TryStartingTransition(GetPresContext(), aFrame->GetContent(), oldContext, &newContext); } #endif @@ -887,7 +886,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) } #endif - ReParentStyleContext(child); + ReparentStyleContext(child); } child = child->GetNextSibling(); @@ -907,7 +906,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) nsIFrame* sib = static_cast (aFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling())); if (sib) { - ReParentStyleContext(sib); + ReparentStyleContext(sib); } } @@ -918,8 +917,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) aFrame->GetAdditionalStyleContext(++contextIndex); if (oldExtraContext) { nsRefPtr newExtraContext; - newExtraContext = mStyleSet->ReParentStyleContext(presContext, - oldExtraContext, + newExtraContext = mStyleSet->ReparentStyleContext(oldExtraContext, newContext); if (newExtraContext) { if (newExtraContext != oldExtraContext) { @@ -1505,13 +1503,13 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame, } -nsReStyleHint +nsRestyleHint nsFrameManager::HasAttributeDependentStyle(nsIContent *aContent, nsIAtom *aAttribute, PRInt32 aModType, PRBool aAttrHasChanged) { - nsReStyleHint hint = mStyleSet->HasAttributeDependentStyle(GetPresContext(), + nsRestyleHint hint = mStyleSet->HasAttributeDependentStyle(GetPresContext(), aContent, aAttribute, aModType, @@ -1521,7 +1519,7 @@ nsFrameManager::HasAttributeDependentStyle(nsIContent *aContent, // Perhaps should check that it's XUL, SVG, (or HTML) namespace, but // it doesn't really matter. Or we could even let // HTMLCSSStyleSheetImpl::HasAttributeDependentStyle handle it. - hint = nsReStyleHint(hint | eReStyle_Self); + hint = nsRestyleHint(hint | eRestyle_Self); } return hint; diff --git a/layout/base/nsFrameManager.h b/layout/base/nsFrameManager.h index 5088c67d8188..d26909b6f309 100644 --- a/layout/base/nsFrameManager.h +++ b/layout/base/nsFrameManager.h @@ -148,7 +148,7 @@ public: * * @param aFrame the root of the subtree to reparent. Must not be null. */ - NS_HIDDEN_(nsresult) ReParentStyleContext(nsIFrame* aFrame); + NS_HIDDEN_(nsresult) ReparentStyleContext(nsIFrame* aFrame); /* * Re-resolve the style contexts for a frame tree, building @@ -163,7 +163,7 @@ public: // Determine whether an attribute affects style // If aAttrHasChanged is false, the attribute's value is about to // change. If it's true, it has already changed. - NS_HIDDEN_(nsReStyleHint) HasAttributeDependentStyle(nsIContent *aContent, + NS_HIDDEN_(nsRestyleHint) HasAttributeDependentStyle(nsIContent *aContent, nsIAtom *aAttribute, PRInt32 aModType, PRBool aAttrHasChanged); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 7a33295fcb83..f979f209b849 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -3496,14 +3496,14 @@ PresShell::RecreateFramesFor(nsIContent* aContent) void nsIPresShell::PostRecreateFramesFor(nsIContent* aContent) { - FrameConstructor()->PostRestyleEvent(aContent, eReStyle_Self, + FrameConstructor()->PostRestyleEvent(aContent, eRestyle_Self, nsChangeHint_ReconstructFrame); } void nsIPresShell::RestyleForAnimation(nsIContent* aContent) { - FrameConstructor()->PostAnimationRestyleEvent(aContent, eReStyle_Self, + FrameConstructor()->PostAnimationRestyleEvent(aContent, eRestyle_Self, NS_STYLE_HINT_NONE); } @@ -4750,7 +4750,7 @@ PresShell::DocumentStatesChanged(nsIDocument* aDocument, mDocument->GetRootContent(), aStateMask)) { mFrameConstructor->PostRestyleEvent(mDocument->GetRootContent(), - eReStyle_Self, NS_STYLE_HINT_NONE); + eRestyle_Self, NS_STYLE_HINT_NONE); VERIFY_STYLE_TREE; } } @@ -4924,7 +4924,7 @@ nsIPresShell::ReconstructStyleDataInternal() return; } - mFrameConstructor->PostRestyleEvent(root, eReStyle_Self, NS_STYLE_HINT_NONE); + mFrameConstructor->PostRestyleEvent(root, eRestyle_Self, NS_STYLE_HINT_NONE); #ifdef ACCESSIBILITY InvalidateAccessibleSubtree(nsnull); diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index d6486ec260d9..dbea8cc62ab2 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -120,7 +120,7 @@ public: protected: virtual PRIntn GetSkipSides() const; - void ReParentFrameList(const nsFrameList& aFrameList); + void ReparentFrameList(const nsFrameList& aFrameList); nsIFrame* mLegendFrame; nsIFrame* mContentFrame; @@ -621,7 +621,7 @@ nsFieldSetFrame::AppendFrames(nsIAtom* aListName, nsFrameList& aFrameList) { // aFrameList is not allowed to contain "the legend" for this fieldset - ReParentFrameList(aFrameList); + ReparentFrameList(aFrameList); return mContentFrame->AppendFrames(aListName, aFrameList); } @@ -635,7 +635,7 @@ nsFieldSetFrame::InsertFrames(nsIAtom* aListName, "inserting after sibling frame with different parent"); // aFrameList is not allowed to contain "the legend" for this fieldset - ReParentFrameList(aFrameList); + ReparentFrameList(aFrameList); if (NS_UNLIKELY(aPrevFrame == mLegendFrame)) { aPrevFrame = nsnull; } @@ -665,14 +665,14 @@ NS_IMETHODIMP nsFieldSetFrame::GetAccessible(nsIAccessible** aAccessible) #endif void -nsFieldSetFrame::ReParentFrameList(const nsFrameList& aFrameList) +nsFieldSetFrame::ReparentFrameList(const nsFrameList& aFrameList) { nsFrameManager* frameManager = PresContext()->FrameManager(); for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) { NS_ASSERTION(mLegendFrame || e.get()->GetType() != nsGkAtoms::legendFrame, "The fieldset's legend is not allowed in this list"); e.get()->SetParent(mContentFrame); - frameManager->ReParentStyleContext(e.get()); + frameManager->ReparentStyleContext(e.get()); } mContentFrame->AddStateBits(GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW); } diff --git a/layout/generic/Makefile.in b/layout/generic/Makefile.in index 9c243918895c..71520d1b8527 100644 --- a/layout/generic/Makefile.in +++ b/layout/generic/Makefile.in @@ -69,6 +69,7 @@ EXPORTS = \ nsIScrollableFrame.h \ nsIStatefulFrame.h \ nsFrameSelection.h \ + nsPluginUtilsOSX.h \ $(NULL) ifdef IBMBIDI diff --git a/layout/generic/crashtests/414740.html b/layout/generic/crashtests/414740.html deleted file mode 100644 index ef557cc8829f..000000000000 --- a/layout/generic/crashtests/414740.html +++ /dev/null @@ -1,31 +0,0 @@ - -Testcase bug 344164 - Hang when moving right in caret browsing with this testcase - - - -text - - diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index d88b9a687936..c0f806a1eb3b 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -201,6 +201,7 @@ load 426272-1.html load 428263-1.html load 429969-1.html load 429981-1.html +load 430332-1.html load 430344-1.html load 430352-1.html load 430744-1.html diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 08d38947975c..47ffdefc0647 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -108,7 +108,7 @@ nsFirstLetterFrame::SetInitialChildList(nsIAtom* aListName, for (nsFrameList::Enumerator e(aChildList); !e.AtEnd(); e.Next()) { NS_ASSERTION(e.get()->GetParent() == this, "Unexpected parent"); - frameManager->ReParentStyleContext(e.get()); + frameManager->ReparentStyleContext(e.get()); } mFrames.SetFrames(aChildList); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e355927b553a..cbe4a9a2f7d8 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -973,6 +973,13 @@ nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder, new (aBuilder) nsDisplayCaret(this, aBuilder->GetCaret())); } +nscolor +nsIFrame::GetCaretColorAt(PRInt32 aOffset) +{ + // Use text color. + return GetStyleColor()->mColor; +} + PRBool nsIFrame::HasBorder() const { @@ -5817,7 +5824,7 @@ nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent, } // Otherwise, walk up out of all anon boxes. For placeholder frames, walk out - // of all pseudo-elements as well. Otherwise ReParentStyleContext could cause + // of all pseudo-elements as well. Otherwise ReparentStyleContext could cause // style data to be out of sync with the frame tree. nsIFrame* parent = aProspectiveParent; do { diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 469f1def77ad..b367a5eefd7c 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -710,16 +710,22 @@ nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs, } } +static nsIFrame* +GetNearestContainingBlock(nsIFrame *aFrame) +{ + nsIFrame *cb = aFrame; + do { + cb = cb->GetParent(); + } while (!cb->IsContainingBlock()); + return cb; +} + nsIFrame* nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame, nscoord& aCBLeftEdge, nscoord& aCBWidth) { - do { - aFrame = aFrame->GetParent(); - NS_ASSERTION(aFrame, "Must find containing block somewhere"); - } while (!aFrame->IsContainingBlock()); - + aFrame = GetNearestContainingBlock(aFrame); NS_ASSERTION(aFrame != frame, "How did that happen?"); /* Now aFrame is the containing block we want */ @@ -753,16 +759,6 @@ nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame, return aFrame; } -static nsIFrame* -GetNearestContainingBlock(nsIFrame *aFrame) -{ - nsIFrame *cb = aFrame; - do { - cb = cb->GetParent(); - } while (!cb->IsContainingBlock()); - return cb; -} - // When determining the hypothetical box that would have been if the element // had been in the flow we may not be able to exactly determine both the left // and right edges. For example, if the element is a non-replaced inline-level @@ -966,14 +962,19 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext, const nsStyleVisibility* blockVis = aContainingBlock->GetStyleVisibility(); // Get the placeholder x-offset and y-offset in the coordinate - // space of the block frame that contains it + // space of its containing block // XXXbz the placeholder is not fully reflowed yet if our containing block is // relatively positioned... nsPoint placeholderOffset = aPlaceholderFrame->GetOffsetTo(aContainingBlock); - // First, determine the hypothetical box's mTop - nsBlockFrame* blockFrame = nsLayoutUtils::GetAsBlock(aContainingBlock); + // First, determine the hypothetical box's mTop. We want to check the + // content insertion frame of aContainingBlock for block-ness, but make + // sure to compute all coordinates in the coordinate system of + // aContainingBlock. + nsBlockFrame* blockFrame = + nsLayoutUtils::GetAsBlock(aContainingBlock->GetContentInsertionFrame()); if (blockFrame) { + nscoord blockYOffset = blockFrame->GetOffsetTo(aContainingBlock).y; PRBool isValid; nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid); NS_ASSERTION(isValid, "Can't find placeholder!"); @@ -985,7 +986,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext, if (NS_STYLE_DISPLAY_INLINE == mStyleDisplay->mOriginalDisplay) { // Use the top of the inline box which the placeholder lives in as the // hypothetical box's top. - aHypotheticalBox.mTop = lineBox->mBounds.y; + aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset; } else { // The element would have been block-level which means it would be below // the line containing the placeholder frame, unless all the frames @@ -1010,14 +1011,14 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext, // The top of the hypothetical box is the top of the line containing // the placeholder, since there is nothing in the line before our // placeholder except empty frames. - aHypotheticalBox.mTop = lineBox->mBounds.y; + aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset; } else { // The top of the hypothetical box is just below the line containing // the placeholder. - aHypotheticalBox.mTop = lineBox->mBounds.YMost(); + aHypotheticalBox.mTop = lineBox->mBounds.YMost() + blockYOffset; } } else { - // Just use the placeholder's y-offset + // Just use the placeholder's y-offset wrt the containing block aHypotheticalBox.mTop = placeholderOffset.y; } } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 565627994472..81a99cbe6ba6 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -977,6 +977,13 @@ public: const nsRect& aDirtyRect, nsDisplayList* aList); + /** + * Get the preferred caret color at the offset. + * + * @param aOffset is offset of the content. + */ + virtual nscolor GetCaretColorAt(PRInt32 aOffset); + PRBool IsThemed(nsTransparencyMode* aTransparencyMode = nsnull) { return IsThemed(GetStyleDisplay(), aTransparencyMode); } diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 927392224eb9..40b949462bdd 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -304,7 +304,7 @@ nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer, } static void -ReParentChildListStyle(nsPresContext* aPresContext, +ReparentChildListStyle(nsPresContext* aPresContext, const nsFrameList::Slice& aFrames, nsIFrame* aParentFrame) { @@ -312,7 +312,7 @@ ReParentChildListStyle(nsPresContext* aPresContext, for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) { NS_ASSERTION(e.get()->GetParent() == aParentFrame, "Bogus parentage"); - frameManager->ReParentStyleContext(e.get()); + frameManager->ReparentStyleContext(e.get()); } } @@ -374,7 +374,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext, // we reparent the style contexts when we set their parents in // nsInlineFrame::ReflowFrames and nsInlineFrame::ReflowInlineFrame. if (aReflowState.mLineLayout->GetInFirstLine()) { - ReParentChildListStyle(aPresContext, newFrames, this); + ReparentChildListStyle(aPresContext, newFrames, this); } } } @@ -522,7 +522,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, } frame->SetParent(this); if (inFirstLine) { - frameManager->ReParentStyleContext(frame); + frameManager->ReparentStyleContext(frame); } // We also need to check if frame has a next-in-flow. If it does, then set // its parent frame pointer, too. Otherwise, if we reflow frame and it's @@ -540,7 +540,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, } nextInFlow->SetParent(this); if (inFirstLine) { - frameManager->ReParentStyleContext(nextInFlow); + frameManager->ReparentStyleContext(nextInFlow); } } @@ -559,7 +559,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, if (mFrames.ContainsFrame(nextInFlow)) { nextInFlow->SetParent(this); if (inFirstLine) { - frameManager->ReParentStyleContext(nextInFlow); + frameManager->ReparentStyleContext(nextInFlow); } } else { @@ -744,7 +744,7 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext, for (nsIFrame* f = aFrame->GetNextSibling(); f; f = f->GetNextSibling()) { f->SetParent(this); if (lineLayout->GetInFirstLine()) { - aPresContext->FrameManager()->ReParentStyleContext(f); + aPresContext->FrameManager()->ReparentStyleContext(f); } } } @@ -1005,7 +1005,7 @@ nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowState& i // We are a first-line frame. Fixup the child frames // style-context that we just pulled. NS_ASSERTION(frame->GetParent() == this, "Incorrect parent?"); - aPresContext->FrameManager()->ReParentStyleContext(frame); + aPresContext->FrameManager()->ReparentStyleContext(frame); } return frame; } @@ -1035,7 +1035,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, } const nsFrameList::Slice& newFrames = mFrames.InsertFrames(this, nsnull, *prevOverflowFrames); - ReParentChildListStyle(aPresContext, newFrames, this); + ReparentChildListStyle(aPresContext, newFrames, this); } } @@ -1046,7 +1046,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, const nsFrameList::Slice& newFrames = mFrames.AppendFrames(nsnull, *overflowFrames); - ReParentChildListStyle(aPresContext, newFrames, this); + ReparentChildListStyle(aPresContext, newFrames, this); } // Set our own reflow state (additional state above and beyond @@ -1108,7 +1108,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, SetStyleContext(newSC); // Re-resolve all children - ReParentChildListStyle(aPresContext, mFrames, this); + ReparentChildListStyle(aPresContext, mFrames, this); } } } @@ -1135,7 +1135,7 @@ nsFirstLineFrame::PullOverflowsFromPrevInFlow() // Assume that our prev-in-flow has the same line container that we do. const nsFrameList::Slice& newFrames = mFrames.InsertFrames(this, nsnull, *prevOverflowFrames); - ReParentChildListStyle(PresContext(), newFrames, this); + ReparentChildListStyle(PresContext(), newFrames, this); } } } diff --git a/layout/generic/nsPluginUtilsOSX.h b/layout/generic/nsPluginUtilsOSX.h index 621d172e7122..6b31fc203869 100644 --- a/layout/generic/nsPluginUtilsOSX.h +++ b/layout/generic/nsPluginUtilsOSX.h @@ -64,6 +64,9 @@ NPBool NS_NPAPI_ConvertPointCocoa(void* inView, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); +// Get the system color space. +CGColorSpaceRef CreateSystemColorSpace(); + // Manages a CARenderer struct _CGLPBufferObject; struct _CGLContextObject; diff --git a/layout/generic/nsPluginUtilsOSX.mm b/layout/generic/nsPluginUtilsOSX.mm index 6e6c01075b43..b4269ccf32a3 100644 --- a/layout/generic/nsPluginUtilsOSX.mm +++ b/layout/generic/nsPluginUtilsOSX.mm @@ -221,15 +221,17 @@ nsCARenderer::~nsCARenderer() { Destroy(); } -CGColorSpaceRef CreateSystemColorSpace () { +CGColorSpaceRef CreateSystemColorSpace() { CMProfileRef system_profile = NULL; CGColorSpaceRef cspace = NULL; if (::CMGetSystemProfile(&system_profile) == noErr) { // Create a colorspace with the systems profile cspace = ::CGColorSpaceCreateWithPlatformColorSpace(system_profile); - ::CMCloseProfile(system_profile); + } else { + // Default to generic + cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); } return cspace; diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 757f5b68d87a..8bbe7b9a54b7 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -307,6 +307,8 @@ public: SelectionDetails* aDetails, SelectionType aSelectionType); + virtual nscolor GetCaretColorAt(PRInt32 aOffset); + PRInt16 GetSelectionStatus(PRInt16* aSelectionFlags); #ifdef DEBUG diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 70aad785e472..72af465d0119 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -4717,6 +4717,48 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, return PR_TRUE; } +nscolor +nsTextFrame::GetCaretColorAt(PRInt32 aOffset) +{ + NS_PRECONDITION(aOffset >= 0, "aOffset must be positive"); + + gfxSkipCharsIterator iter = EnsureTextRun(); + PropertyProvider provider(this, iter); + PRInt32 contentOffset = provider.GetStart().GetOriginalOffset(); + PRInt32 contentLength = provider.GetOriginalLength(); + NS_PRECONDITION(aOffset >= contentOffset && + aOffset <= contentOffset + contentLength, + "aOffset must be in the frame's range"); + PRInt32 offsetInFrame = aOffset - contentOffset; + if (offsetInFrame < 0 || offsetInFrame >= contentLength) { + return nsFrame::GetCaretColorAt(aOffset); + } + + nsTextPaintStyle textPaintStyle(this); + SelectionDetails* details = GetSelectionDetails(); + SelectionDetails* sdptr = details; + nscolor result = nsFrame::GetCaretColorAt(aOffset); + SelectionType type = 0; + while (sdptr) { + PRInt32 start = NS_MAX(0, sdptr->mStart - contentOffset); + PRInt32 end = NS_MIN(contentLength, sdptr->mEnd - contentOffset); + if (start <= offsetInFrame && offsetInFrame < end && + (type == 0 || sdptr->mType < type)) { + nscolor foreground, background; + if (GetSelectionTextColors(sdptr->mType, textPaintStyle, + sdptr->mTextRangeStyle, + &foreground, &background)) { + result = foreground; + type = sdptr->mType; + } + } + sdptr = sdptr->mNext; + } + + DestroySelectionDetails(details); + return result; +} + static PRUint32 ComputeTransformedLength(PropertyProvider& aProvider) { diff --git a/layout/mathml/nsMathMLTokenFrame.cpp b/layout/mathml/nsMathMLTokenFrame.cpp index 7e07ff57241e..0d4074e01ee5 100644 --- a/layout/mathml/nsMathMLTokenFrame.cpp +++ b/layout/mathml/nsMathMLTokenFrame.cpp @@ -276,7 +276,7 @@ nsMathMLTokenFrame::ProcessTextData() // explicitly request a re-resolve to pick up the change of style PresContext()->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(mContent, eRestyle_Self, NS_STYLE_HINT_NONE); } /////////////////////////////////////////////////////////////////////////// diff --git a/layout/mathml/nsMathMLmtableFrame.cpp b/layout/mathml/nsMathMLmtableFrame.cpp index 8ca08e3e4573..b8b172312a00 100644 --- a/layout/mathml/nsMathMLmtableFrame.cpp +++ b/layout/mathml/nsMathMLmtableFrame.cpp @@ -525,7 +525,7 @@ nsMathMLmtableOuterFrame::AttributeChanged(PRInt32 aNameSpaceID, // Explicitly request a re-resolve and reflow in our subtree to pick up any changes presContext->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, nsChangeHint_ReflowFrame); + PostRestyleEvent(mContent, eRestyle_Self, nsChangeHint_ReflowFrame); return NS_OK; } @@ -704,7 +704,7 @@ nsMathMLmtableFrame::RestyleTable() // Explicitly request a re-resolve and reflow in our subtree to pick up any changes PresContext()->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, nsChangeHint_ReflowFrame); + PostRestyleEvent(mContent, eRestyle_Self, nsChangeHint_ReflowFrame); } // -------- @@ -764,7 +764,7 @@ nsMathMLmtrFrame::AttributeChanged(PRInt32 aNameSpaceID, // Explicitly request a re-resolve and reflow in our subtree to pick up any changes presContext->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, nsChangeHint_ReflowFrame); + PostRestyleEvent(mContent, eRestyle_Self, nsChangeHint_ReflowFrame); return NS_OK; } diff --git a/layout/printing/nsPrintData.h b/layout/printing/nsPrintData.h index bd6dbf322e38..97dfb4f468d8 100644 --- a/layout/printing/nsPrintData.h +++ b/layout/printing/nsPrintData.h @@ -44,6 +44,7 @@ #include "nsIPrintOptions.h" #include "nsTArray.h" #include "nsCOMArray.h" +#include "nsAutoPtr.h" // Classes class nsPrintObject; diff --git a/layout/reftests/bugs/383488-1-ref.html b/layout/reftests/bugs/383488-1-ref.html new file mode 100644 index 000000000000..0b2df13e5a2b --- /dev/null +++ b/layout/reftests/bugs/383488-1-ref.html @@ -0,0 +1,28 @@ + + + + +

The X'es below should have the same size:

+ +

XXXXXXXXXXXXXXXX

+ + diff --git a/layout/reftests/bugs/383488-1.html b/layout/reftests/bugs/383488-1.html new file mode 100644 index 000000000000..cd5df2b4b86c --- /dev/null +++ b/layout/reftests/bugs/383488-1.html @@ -0,0 +1,53 @@ + + + + + +

The X'es below should have the same size:

+ +

XXXXXXXXXXXXXXXX

+ diff --git a/layout/reftests/bugs/551699-1-ref.html b/layout/reftests/bugs/551699-1-ref.html new file mode 100644 index 000000000000..1f81b34f38c4 --- /dev/null +++ b/layout/reftests/bugs/551699-1-ref.html @@ -0,0 +1,13 @@ + + + + + + + +
+
Text
+
+
+ + diff --git a/layout/reftests/bugs/551699-1.html b/layout/reftests/bugs/551699-1.html new file mode 100644 index 000000000000..a97921c4fdcf --- /dev/null +++ b/layout/reftests/bugs/551699-1.html @@ -0,0 +1,13 @@ + + + + + + + +
+
Text
+
+
+ + diff --git a/layout/reftests/bugs/552334-1-ref.html b/layout/reftests/bugs/552334-1-ref.html new file mode 100644 index 000000000000..a139827f2c40 --- /dev/null +++ b/layout/reftests/bugs/552334-1-ref.html @@ -0,0 +1,15 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/bugs/552334-1.html b/layout/reftests/bugs/552334-1.html new file mode 100644 index 000000000000..66f426e09b7c --- /dev/null +++ b/layout/reftests/bugs/552334-1.html @@ -0,0 +1,26 @@ + + + + + + + +
+
+ +
+
+ +
+
+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 3ae1b44010e6..78e99d0b528c 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -671,6 +671,7 @@ random-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 379316-2.html 379316-2-ref.html # bug == 382916-1.html 382916-1-ref.html == 383035-1.html about:blank == 383035-2.html about:blank +== 383488-1.html 383488-1-ref.html == 383551-1.html 383551-1-ref.html == 383883-1.html 383883-1-ref.html == 383883-2.html 383883-2-ref.html @@ -1418,3 +1419,5 @@ random-if(!haveTestPlugin) == 546071-1.html 546071-1-ref.html == 549184-1.html 549184-1-ref.html == 550716-1.html 550716-1-ref.html == 551463-1.html 551463-1-ref.html +== 552334-1.html 552334-1-ref.html +== 551699-1.html 551699-1-ref.html diff --git a/layout/style/crashtests/509569-1.html b/layout/style/crashtests/509569-1.html new file mode 100644 index 000000000000..023c710401ee --- /dev/null +++ b/layout/style/crashtests/509569-1.html @@ -0,0 +1,2 @@ + + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index 8d22e2346141..474d070cb1af 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -48,6 +48,7 @@ load 495269-2.html load 498036-1.html load 509155-1.html load 509156-1.html +load 509569-1.html load 524252-1.html load font-face-truncated-src.html load 536789-1.html diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 70ec1e2c1c4b..1d59799240ed 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -215,7 +215,8 @@ public: nsIURI* aBaseURL, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged); + PRBool* aChanged, + PRBool aIsImportant); nsresult ParseMediaList(const nsSubstring& aBuffer, nsIURI* aURL, // for error reporting @@ -1089,7 +1090,8 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, nsIURI* aBaseURI, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged) + PRBool* aChanged, + PRBool aIsImportant) { NS_PRECONDITION(aSheetPrincipal, "Must have principal here!"); AssertInitialState(); @@ -1117,17 +1119,20 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, mData.AssertInitialState(); mTempData.AssertInitialState(); - // We know that our new value is not !important, and that we don't need to - // force a ValueAppended call for it. So if there's already a value for this - // property in the declaration, and it's not !important, and our prop is not - // a shorthand, we parse successfully, then we can just directly copy our - // parsed value into the declaration without going through the whole - // expand/compress thing. + // We know we don't need to force a ValueAppended call for the new + // value. So if we are not processing an !important decl or a + // shorthand, there's already a value for this property in the + // declaration, it's not !important, and we parse successfully, then + // we can just directly copy our parsed value into the declaration + // without going through the whole expand/compress thing. if (!aDeclaration->EnsureMutable()) { NS_WARNING("out of memory"); return NS_ERROR_OUT_OF_MEMORY; } - void* valueSlot = aDeclaration->SlotForValue(aPropID); + void* valueSlot = nsnull; + if (!aIsImportant) { + valueSlot = aDeclaration->SlotForValue(aPropID); + } if (!valueSlot) { // Do it the slow way aDeclaration->ExpandTo(&mData); @@ -1139,7 +1144,7 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, CopyValue(mTempData.PropertyAt(aPropID), valueSlot, aPropID, aChanged); mTempData.ClearPropertyBit(aPropID); } else { - TransferTempData(aDeclaration, aPropID, PR_FALSE, PR_FALSE, aChanged); + TransferTempData(aDeclaration, aPropID, aIsImportant, PR_FALSE, aChanged); } } else { if (parsedOK) { @@ -9229,11 +9234,12 @@ nsCSSParser::ParseProperty(const nsCSSProperty aPropID, nsIURI* aBaseURI, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged) + PRBool* aChanged, + PRBool aIsImportant) { return static_cast(mImpl)-> ParseProperty(aPropID, aPropValue, aSheetURI, aBaseURI, - aSheetPrincipal, aDeclaration, aChanged); + aSheetPrincipal, aDeclaration, aChanged, aIsImportant); } nsresult diff --git a/layout/style/nsCSSParser.h b/layout/style/nsCSSParser.h index f0bbe971e002..2f5135d64657 100644 --- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -151,7 +151,8 @@ public: nsIURI* aBaseURL, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged); + PRBool* aChanged, + PRBool aIsImportant); /** * Parse aBuffer into a media list |aMediaList|, which must be diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 258f3c755f85..41361dc1f272 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -2271,7 +2271,7 @@ IsSiblingOperator(PRUnichar oper) return oper == PRUnichar('+') || oper == PRUnichar('~'); } -nsReStyleHint +nsRestyleHint nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) { NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT), @@ -2287,15 +2287,15 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) // "body > p:hover" will be in |cascade->mStateSelectors|). Note that // |IsStateSelector| below determines which selectors are in // |cascade->mStateSelectors|. - nsReStyleHint hint = nsReStyleHint(0); + nsRestyleHint hint = nsRestyleHint(0); if (cascade) { nsCSSSelector **iter = cascade->mStateSelectors.Elements(), **end = iter + cascade->mStateSelectors.Length(); for(; iter != end; ++iter) { nsCSSSelector* selector = *iter; - nsReStyleHint possibleChange = IsSiblingOperator(selector->mOperator) ? - eReStyle_LaterSiblings : eReStyle_Self; + nsRestyleHint possibleChange = IsSiblingOperator(selector->mOperator) ? + eRestyle_LaterSiblings : eRestyle_Self; // If hint already includes all the bits of possibleChange, // don't bother calling SelectorMatches, since even if it returns false @@ -2303,7 +2303,7 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) if ((possibleChange & ~hint) && SelectorMatches(*aData, selector, aData->mStateMask, PR_FALSE) && SelectorMatchesTree(*aData, selector->mNext, PR_FALSE)) { - hint = nsReStyleHint(hint | possibleChange); + hint = nsRestyleHint(hint | possibleChange); } } } @@ -2320,10 +2320,10 @@ nsCSSRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessorData* aData struct AttributeEnumData { AttributeEnumData(AttributeRuleProcessorData *aData) - : data(aData), change(nsReStyleHint(0)) {} + : data(aData), change(nsRestyleHint(0)) {} AttributeRuleProcessorData *data; - nsReStyleHint change; + nsRestyleHint change; }; @@ -2332,8 +2332,8 @@ AttributeEnumFunc(nsCSSSelector* aSelector, AttributeEnumData* aData) { AttributeRuleProcessorData *data = aData->data; - nsReStyleHint possibleChange = IsSiblingOperator(aSelector->mOperator) ? - eReStyle_LaterSiblings : eReStyle_Self; + nsRestyleHint possibleChange = IsSiblingOperator(aSelector->mOperator) ? + eRestyle_LaterSiblings : eRestyle_Self; // If enumData->change already includes all the bits of possibleChange, don't // bother calling SelectorMatches, since even if it returns false @@ -2341,11 +2341,11 @@ AttributeEnumFunc(nsCSSSelector* aSelector, AttributeEnumData* aData) if ((possibleChange & ~(aData->change)) && SelectorMatches(*data, aSelector, 0, PR_FALSE) && SelectorMatchesTree(*data, aSelector->mNext, PR_FALSE)) { - aData->change = nsReStyleHint(aData->change | possibleChange); + aData->change = nsRestyleHint(aData->change | possibleChange); } } -nsReStyleHint +nsRestyleHint nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT), @@ -2365,7 +2365,7 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData aData->mNameSpaceID == kNameSpaceID_XUL && aData->mContent == aData->mContent->GetOwnerDoc()->GetRootContent()) { - data.change = nsReStyleHint(data.change | eReStyle_Self); + data.change = nsRestyleHint(data.change | eRestyle_Self); } } diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index ff785d62e021..89c4053036ae 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -102,11 +102,11 @@ public: NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index 548a969c429c..f2a940779659 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -506,8 +506,7 @@ nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer, : mURI(aURI), mString(aString), mReferrer(aReferrer), - mOriginPrincipal(aOriginPrincipal), - mRefCnt(0) + mOriginPrincipal(aOriginPrincipal) { NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal"); mString->AddRef(); @@ -593,7 +592,6 @@ nsCSSValueGradient::nsCSSValueGradient(PRBool aIsRadial, mBgPosY(eCSSUnit_None), mAngle(eCSSUnit_None), mRadialShape(eCSSUnit_None), - mRadialSize(eCSSUnit_None), - mRefCnt(0) + mRadialSize(eCSSUnit_None) { } diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 35db8b4d3003..9c6a4278f2ca 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -51,6 +51,7 @@ #include "nsCRTGlue.h" #include "nsStringBuffer.h" #include "nsTArray.h" +#include "nsISupportsImpl.h" class imgIRequest; class nsIDocument; @@ -379,26 +380,9 @@ public: nsCOMPtr mReferrer; nsCOMPtr mOriginPrincipal; - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::URL", sizeof(*this)); - } - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::URL"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(nsCSSValue::URL) + protected: - nsrefcnt mRefCnt; // not to be implemented URL(const URL& aOther); @@ -420,25 +404,7 @@ public: // Override AddRef and Release to not only log ourselves correctly, but // also so that we delete correctly without a virtual destructor - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Image", sizeof(*this)); - } - - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Image"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(nsCSSValue::Image) }; private: @@ -529,28 +495,9 @@ struct nsCSSValueGradient { return !(*this == aOther); } - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Gradient", sizeof(*this)); - } - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Gradient"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient) private: - nsrefcnt mRefCnt; - // not to be implemented nsCSSValueGradient(const nsCSSValueGradient& aOther); nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther); @@ -588,6 +535,8 @@ struct nsCSSValue::Array { return PR_TRUE; } + // XXXdholbert This uses a 16-bit ref count to save space. Should we use + // a variant of NS_INLINE_DECL_REFCOUNTING that takes a type as an argument? void AddRef() { if (mRefCnt == PR_UINT16_MAX) { NS_WARNING("refcount overflow, leaking nsCSSValue::Array"); diff --git a/layout/style/nsDOMCSSDeclaration.cpp b/layout/style/nsDOMCSSDeclaration.cpp index 30b4a8ca8e46..6b69ca375fcb 100644 --- a/layout/style/nsDOMCSSDeclaration.cpp +++ b/layout/style/nsDOMCSSDeclaration.cpp @@ -103,7 +103,7 @@ nsDOMCSSDeclaration::SetPropertyValue(const nsCSSProperty aPropID, return RemoveProperty(aPropID); } - return ParsePropertyValue(aPropID, aValue); + return ParsePropertyValue(aPropID, aValue, PR_FALSE); } @@ -206,24 +206,24 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName, if (propID == eCSSProperty_UNKNOWN) { return NS_OK; } - + if (aValue.IsEmpty()) { // If the new value of the property is an empty string we remove the // property. + // XXX this ignores the priority string, should it? return RemoveProperty(propID); } if (aPriority.IsEmpty()) { - return ParsePropertyValue(propID, aValue); + return ParsePropertyValue(propID, aValue, PR_FALSE); } - // ParsePropertyValue does not handle priorities correctly -- it's - // optimized for speed. And the priority is not part of the - // property value anyway.... So we have to use the full-blown - // ParseDeclaration() - return ParseDeclaration(aPropertyName + NS_LITERAL_STRING(":") + - aValue + NS_LITERAL_STRING("!") + aPriority, - PR_TRUE, PR_FALSE); + if (aPriority.EqualsLiteral("important")) { + return ParsePropertyValue(propID, aValue, PR_TRUE); + } + + // XXX silent failure? + return NS_OK; } NS_IMETHODIMP @@ -245,7 +245,8 @@ nsDOMCSSDeclaration::RemoveProperty(const nsAString& aPropertyName, nsresult nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSProperty aPropID, - const nsAString& aPropValue) + const nsAString& aPropValue, + PRBool aIsImportant) { nsCSSDeclaration* decl; nsresult result = GetCSSDeclaration(&decl, PR_TRUE); @@ -275,7 +276,8 @@ nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSProperty aPropID, nsCSSParser cssParser(cssLoader); PRBool changed; result = cssParser.ParseProperty(aPropID, aPropValue, sheetURI, baseURI, - sheetPrincipal, decl, &changed); + sheetPrincipal, decl, &changed, + aIsImportant); if (NS_SUCCEEDED(result) && changed) { result = DeclarationChanged(); } diff --git a/layout/style/nsDOMCSSDeclaration.h b/layout/style/nsDOMCSSDeclaration.h index e86c6cb4c1dd..8eaa102970ee 100644 --- a/layout/style/nsDOMCSSDeclaration.h +++ b/layout/style/nsDOMCSSDeclaration.h @@ -122,7 +122,8 @@ protected: mozilla::css::Loader** aCSSLoader) = 0; nsresult ParsePropertyValue(const nsCSSProperty aPropID, - const nsAString& aPropValue); + const nsAString& aPropValue, + PRBool aIsImportant); nsresult ParseDeclaration(const nsAString& aDecl, PRBool aParseOnlyOneDecl, PRBool aClearOldDecl); diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index fe8cf4213d6b..ed9e5faeade0 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -142,10 +142,10 @@ nsHTMLCSSStyleSheet::Init(nsIURI* aURL, nsIDocument* aDocument) } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsHTMLCSSStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } PRBool @@ -155,10 +155,10 @@ nsHTMLCSSStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aDat } // Test if style is dependent on attribute -nsReStyleHint +nsRestyleHint nsHTMLCSSStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } NS_IMETHODIMP diff --git a/layout/style/nsHTMLCSSStyleSheet.h b/layout/style/nsHTMLCSSStyleSheet.h index 603b61253ca0..8cd4fce181c3 100644 --- a/layout/style/nsHTMLCSSStyleSheet.h +++ b/layout/style/nsHTMLCSSStyleSheet.h @@ -79,9 +79,9 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, PRBool* aResult); diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 76f2914d1236..680e9e34e0bd 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -286,7 +286,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) { if (aData->mIsHTMLContent && @@ -295,10 +295,10 @@ nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) ((mActiveRule && (aData->mStateMask & NS_EVENT_STATE_ACTIVE)) || (mLinkRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)) || (mVisitedRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)))) { - return eReStyle_Self; + return eRestyle_Self; } - return nsReStyleHint(0); + return nsRestyleHint(0); } PRBool @@ -307,12 +307,12 @@ nsHTMLStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) return PR_FALSE; } -nsReStyleHint +nsRestyleHint nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { // Do nothing on before-change checks if (!aData->mAttrHasChanged) { - return nsReStyleHint(0); + return nsRestyleHint(0); } // Note: no need to worry about whether some states changed with this @@ -326,7 +326,7 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) content && content->IsHTML() && aData->mContentTag == nsGkAtoms::a) { - return eReStyle_Self; + return eRestyle_Self; } // Don't worry about the mDocumentColorRule since it only applies @@ -334,10 +334,10 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) // Handle the content style rules. if (content && content->IsAttributeMapped(aData->mAttribute)) { - return eReStyle_Self; + return eRestyle_Self; } - return nsReStyleHint(0); + return nsRestyleHint(0); } NS_IMETHODIMP diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index 46f7fe2d761e..8c7ad8e31c0f 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -84,9 +84,9 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, PRBool* aRulesChanged); diff --git a/layout/style/nsIStyleRuleProcessor.h b/layout/style/nsIStyleRuleProcessor.h index b9b206bb925f..3b6a6e4c91c3 100644 --- a/layout/style/nsIStyleRuleProcessor.h +++ b/layout/style/nsIStyleRuleProcessor.h @@ -118,14 +118,14 @@ public: HasDocumentStateDependentStyle(StateRuleProcessorData* aData) = 0; /** - * Return how (as described by nsReStyleHint) style can depend on a + * Return how (as described by nsRestyleHint) style can depend on a * change of the given content state on the given content node. This * test is used for optimization only, and may err on the side of * reporting more dependencies than really exist. * * Event states are defined in nsIEventStateManager.h. */ - virtual nsReStyleHint + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) = 0; /** @@ -144,7 +144,7 @@ public: * only, and may err on the side of reporting more dependencies than * really exist. */ - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData) = 0; /** diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index a4f79a9bc355..cb9ce6b9ec59 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -2326,6 +2326,12 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext, if (RTLlogical) aValueRect.*(nsCSSRect::sides[aSide]) = aRTLLogicalValue; } + } else if (aLTRLogicalValue.GetUnit() == eCSSUnit_Inherit || + aRTLLogicalValue.GetUnit() == eCSSUnit_Inherit) { + // It actually is valid to store this in the ruletree, since + // LTRlogical and RTLlogical are both false, but doing that will + // trigger asserts. Silence those. + aCanStoreInRuleTree = PR_FALSE; } } diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 9a1e03cd5873..8954f5d56a7e 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -954,7 +954,7 @@ BuildStyleRule(nsCSSProperty aProperty, NS_FAILED(parser.ParseProperty(aProperty, aSpecifiedValue, doc->GetDocumentURI(), baseURI, aTargetElement->NodePrincipal(), - declaration, &changed)) || + declaration, &changed, PR_FALSE)) || // check whether property parsed without CSS parsing errors !declaration->HasNonImportantValueFor(propertyToCheck) || NS_FAILED(NS_NewCSSStyleRule(getter_AddRefs(styleRule), nsnull, diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 188fd9b86551..7a3e1a720ce1 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -427,8 +427,7 @@ EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) * |aParentContext| could itself be a shared context.) */ already_AddRefed -nsStyleSet::GetContext(nsPresContext* aPresContext, - nsStyleContext* aParentContext, +nsStyleSet::GetContext(nsStyleContext* aParentContext, nsRuleNode* aRuleNode, nsIAtom* aPseudoTag, nsCSSPseudoElements::Type aPseudoType) @@ -442,7 +441,7 @@ nsStyleSet::GetContext(nsPresContext* aPresContext, "Pseudo mismatch"); nsStyleContext* result = nsnull; - + if (aParentContext) result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode).get(); @@ -455,7 +454,7 @@ nsStyleSet::GetContext(nsPresContext* aPresContext, if (!result) { result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType, - aRuleNode, aPresContext).get(); + aRuleNode, PresContext()).get(); if (!aParentContext && result) mRoots.AppendElement(result); } @@ -740,25 +739,16 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent, nsStyleContext* aParentContext) { NS_ENSURE_FALSE(mInShutdown, nsnull); - - nsStyleContext* result = nsnull; - nsPresContext* presContext = PresContext(); + NS_ASSERTION(aContent && aContent->IsNodeOfType(nsINode::eELEMENT), + "aContent must be element"); - NS_ASSERTION(aContent, "must have content"); - NS_ASSERTION(aContent->IsNodeOfType(nsINode::eELEMENT), - "content must be element"); + nsRuleWalker ruleWalker(mRuleTree); + ElementRuleProcessorData data(PresContext(), aContent, &ruleWalker); + FileRules(EnumRulesMatching, &data, aContent, + &ruleWalker); - if (aContent && presContext) { - nsRuleWalker ruleWalker(mRuleTree); - ElementRuleProcessorData data(presContext, aContent, &ruleWalker); - FileRules(EnumRulesMatching, &data, aContent, - &ruleWalker); - result = GetContext(presContext, aParentContext, - ruleWalker.CurrentNode(), nsnull, - nsCSSPseudoElements::ePseudo_NotPseudoElement).get(); - } - - return result; + return GetContext(aParentContext, ruleWalker.CurrentNode(), + nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement); } already_AddRefed @@ -769,39 +759,27 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext, const nsCOMArray &aRules) { NS_ENSURE_FALSE(mInShutdown, nsnull); - nsStyleContext* result = nsnull; - nsPresContext *presContext = PresContext(); - if (presContext) { - nsRuleWalker ruleWalker(mRuleTree); - if (aRuleNode) - ruleWalker.SetCurrentNode(aRuleNode); - // FIXME: Perhaps this should be passed in, but it probably doesn't - // matter. - ruleWalker.SetLevel(eDocSheet, PR_FALSE, PR_FALSE); - for (PRInt32 i = 0; i < aRules.Count(); i++) { - ruleWalker.Forward(aRules.ObjectAt(i)); - } - result = GetContext(presContext, aParentContext, - ruleWalker.CurrentNode(), aPseudoTag, - aPseudoType).get(); + nsRuleWalker ruleWalker(mRuleTree); + if (aRuleNode) + ruleWalker.SetCurrentNode(aRuleNode); + // FIXME: Perhaps this should be passed in, but it probably doesn't + // matter. + ruleWalker.SetLevel(eDocSheet, PR_FALSE, PR_FALSE); + for (PRInt32 i = 0; i < aRules.Count(); i++) { + ruleWalker.Forward(aRules.ObjectAt(i)); } - return result; + + return GetContext(aParentContext, ruleWalker.CurrentNode(), + aPseudoTag, aPseudoType); } already_AddRefed nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) { - nsStyleContext* result = nsnull; - nsPresContext *presContext = PresContext(); - - if (presContext) { - result = GetContext(presContext, aParentContext, mRuleTree, - nsCSSAnonBoxes::mozNonElement, - nsCSSPseudoElements::ePseudo_AnonBox).get(); - } - - return result; + return GetContext(aParentContext, mRuleTree, + nsCSSAnonBoxes::mozNonElement, + nsCSSPseudoElements::ePseudo_AnonBox); } void @@ -830,14 +808,13 @@ nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent, "aParentContent must be element"); nsRuleWalker ruleWalker(mRuleTree); - nsPresContext *presContext = PresContext(); - PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker, - aType); + PseudoElementRuleProcessorData data(PresContext(), aParentContent, + &ruleWalker, aType); WalkRestrictionRule(aType, &ruleWalker); FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), + return GetContext(aParentContext, ruleWalker.CurrentNode(), nsCSSPseudoElements::GetPseudoAtom(aType), aType); } @@ -847,7 +824,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, nsStyleContext* aParentContext) { NS_ENSURE_FALSE(mInShutdown, nsnull); - + NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, "must have pseudo element type"); NS_ASSERTION(aParentContent && @@ -855,12 +832,9 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, "aParentContent must be element"); nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); - - nsPresContext *presContext = PresContext(); - nsRuleWalker ruleWalker(mRuleTree); - PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker, - aType); + PseudoElementRuleProcessorData data(PresContext(), aParentContent, + &ruleWalker, aType); WalkRestrictionRule(aType, &ruleWalker); // not the root if there was a restriction rule nsRuleNode *adjustedRoot = ruleWalker.CurrentNode(); @@ -873,7 +847,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, } nsRefPtr result = - GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType); + GetContext(aParentContext, ruleNode, pseudoTag, aType); // For :before and :after pseudo-elements, having display: none or no // 'content' property is equivalent to not having the pseudo-element @@ -889,7 +863,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, result = nsnull; } } - + return result.forget(); } @@ -909,12 +883,11 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, #endif nsRuleWalker ruleWalker(mRuleTree); - nsPresContext *presContext = PresContext(); - AnonBoxRuleProcessorData data(presContext, aPseudoTag, &ruleWalker); + AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker); FileRules(EnumRulesMatching, &data, nsnull, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), + return GetContext(aParentContext, ruleWalker.CurrentNode(), aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox); } @@ -934,14 +907,12 @@ nsStyleSet::ResolveXULTreePseudoStyle(nsIContent* aParentContent, "Unexpected pseudo"); nsRuleWalker ruleWalker(mRuleTree); - nsPresContext *presContext = PresContext(); - - XULTreeRuleProcessorData data(presContext, aParentContent, &ruleWalker, + XULTreeRuleProcessorData data(PresContext(), aParentContent, &ruleWalker, aPseudoTag, aComparator); FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), + return GetContext(aParentContext, ruleWalker.CurrentNode(), aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree); } #endif @@ -1042,39 +1013,33 @@ nsStyleSet::GCRuleTrees() } already_AddRefed -nsStyleSet::ReParentStyleContext(nsPresContext* aPresContext, - nsStyleContext* aStyleContext, +nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext, nsStyleContext* aNewParentContext) { - NS_ASSERTION(aPresContext, "must have pres context"); - NS_ASSERTION(aStyleContext, "must have style context"); - - if (aPresContext && aStyleContext) { - if (aStyleContext->GetParent() == aNewParentContext) { - aStyleContext->AddRef(); - return aStyleContext; - } - else { // really a new parent - nsIAtom* pseudoTag = aStyleContext->GetPseudo(); - nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); - nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); - - already_AddRefed result = - GetContext(aPresContext, aNewParentContext, ruleNode, pseudoTag, - pseudoType); - return result; - } + if (!aStyleContext) { + NS_NOTREACHED("must have style context"); + return nsnull; } - return nsnull; + + if (aStyleContext->GetParent() == aNewParentContext) { + aStyleContext->AddRef(); + return aStyleContext; + } + + nsIAtom* pseudoTag = aStyleContext->GetPseudo(); + nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); + nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); + + return GetContext(aNewParentContext, ruleNode, pseudoTag, pseudoType); } struct StatefulData : public StateRuleProcessorData { StatefulData(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask) : StateRuleProcessorData(aPresContext, aContent, aStateMask), - mHint(nsReStyleHint(0)) + mHint(nsRestyleHint(0)) {} - nsReStyleHint mHint; + nsRestyleHint mHint; }; static PRBool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor, @@ -1082,7 +1047,7 @@ static PRBool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor, { StatefulData* data = (StatefulData*)aData; if (aProcessor->HasDocumentStateDependentStyle(data)) { - data->mHint = eReStyle_Self; + data->mHint = eRestyle_Self; return PR_FALSE; // don't continue } return PR_TRUE; // continue @@ -1106,18 +1071,18 @@ static PRBool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { StatefulData* data = (StatefulData*)aData; - nsReStyleHint hint = aProcessor->HasStateDependentStyle(data); - data->mHint = nsReStyleHint(data->mHint | hint); + nsRestyleHint hint = aProcessor->HasStateDependentStyle(data); + data->mHint = nsRestyleHint(data->mHint | hint); return PR_TRUE; // continue } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsStyleSet::HasStateDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask) { - nsReStyleHint result = nsReStyleHint(0); + nsRestyleHint result = nsRestyleHint(0); if (aContent->IsNodeOfType(nsINode::eELEMENT)) { StatefulData data(aPresContext, aContent, aStateMask); @@ -1134,29 +1099,29 @@ struct AttributeData : public AttributeRuleProcessorData { PRBool aAttrHasChanged) : AttributeRuleProcessorData(aPresContext, aContent, aAttribute, aModType, aAttrHasChanged), - mHint(nsReStyleHint(0)) + mHint(nsRestyleHint(0)) {} - nsReStyleHint mHint; + nsRestyleHint mHint; }; static PRBool SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { AttributeData* data = (AttributeData*)aData; - nsReStyleHint hint = aProcessor->HasAttributeDependentStyle(data); - data->mHint = nsReStyleHint(data->mHint | hint); + nsRestyleHint hint = aProcessor->HasAttributeDependentStyle(data); + data->mHint = nsRestyleHint(data->mHint | hint); return PR_TRUE; // continue } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType, PRBool aAttrHasChanged) { - nsReStyleHint result = nsReStyleHint(0); + nsRestyleHint result = nsRestyleHint(0); if (aContent->IsNodeOfType(nsINode::eELEMENT)) { AttributeData data(aPresContext, aContent, aAttribute, aModType, diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index c8fada845157..574baa4df0bb 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -173,9 +173,8 @@ class nsStyleSet // The new context will be the same as the old if the new parent is the // same as the old parent. already_AddRefed - ReParentStyleContext(nsPresContext* aPresContext, - nsStyleContext* aStyleContext, - nsStyleContext* aNewParentContext); + ReparentStyleContext(nsStyleContext* aStyleContext, + nsStyleContext* aNewParentContext); // Test if style is dependent on a document state. PRBool HasDocumentStateDependentStyle(nsPresContext* aPresContext, @@ -183,12 +182,12 @@ class nsStyleSet PRInt32 aStateMask); // Test if style is dependent on content state - nsReStyleHint HasStateDependentStyle(nsPresContext* aPresContext, + nsRestyleHint HasStateDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask); // Test if style is dependent on the presence of an attribute. - nsReStyleHint HasAttributeDependentStyle(nsPresContext* aPresContext, + nsRestyleHint HasAttributeDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType, @@ -336,11 +335,11 @@ class nsStyleSet RuleProcessorData* aData, PRBool aWalkAllXBLStylesheets); - already_AddRefed GetContext(nsPresContext* aPresContext, - nsStyleContext* aParentContext, - nsRuleNode* aRuleNode, - nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType); + already_AddRefed + GetContext(nsStyleContext* aParentContext, + nsRuleNode* aRuleNode, + nsIAtom* aPseudoTag, + nsCSSPseudoElements::Type aPseudoType); nsPresContext* PresContext() { return mRuleTree->GetPresContext(); } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 1368487368d5..4eeb50f86ae2 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1317,7 +1317,6 @@ nsStyleGradient::nsStyleGradient(void) : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR) , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) , mRepeating(PR_FALSE) - , mRefCnt(0) { } @@ -2318,26 +2317,6 @@ nsChangeHint nsStyleTextReset::MaxDifference() } #endif -// -------------------- -// nsCSSShadowArray -// nsCSSShadowItem -// - -nsrefcnt -nsCSSShadowArray::Release() -{ - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - mRefCnt--; - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; -} - // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though. // XXXbz can this not return a more specific hint? If that's ever diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 46be0ae3db1b..77f8e7e0910e 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -163,38 +163,14 @@ public: // stops are in the order specified in the stylesheet nsTArray mStops; - nsrefcnt AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsStyleGradient"); - return mRefCnt; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsStyleGradient", sizeof(*this)); - return mRefCnt; - } - - nsrefcnt Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsStyleGradient"); - return mRefCnt; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsStyleGradient"); - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } - PRBool operator==(const nsStyleGradient& aOther) const; PRBool operator!=(const nsStyleGradient& aOther) const { return !(*this == aOther); }; -private: - nsrefcnt mRefCnt; + NS_INLINE_DECL_REFCOUNTING(nsStyleGradient) +private: ~nsStyleGradient() {} // Not to be implemented @@ -671,7 +647,7 @@ class nsCSSShadowArray { } nsCSSShadowArray(PRUint32 aArrayLen) : - mLength(aArrayLen), mRefCnt(0) + mLength(aArrayLen) { MOZ_COUNT_CTOR(nsCSSShadowArray); for (PRUint32 i = 1; i < mLength; ++i) { @@ -687,15 +663,6 @@ class nsCSSShadowArray { } } - nsrefcnt AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - return ++mRefCnt; - } - nsrefcnt Release(); - PRUint32 Length() const { return mLength; } nsCSSShadowItem* ShadowAt(PRUint32 i) { NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!"); @@ -706,9 +673,10 @@ class nsCSSShadowArray { return &mArray[i]; } + NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray) + private: PRUint32 mLength; - PRUint32 mRefCnt; nsCSSShadowItem mArray[1]; // This MUST be the last item }; diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 36a99f17062a..52533b5e77e5 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -393,7 +393,7 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement, NS_PRECONDITION(aOldStyleContext->GetPseudo() == aNewStyleContext->GetPseudo(), "pseudo type mismatch"); - // If we were called from ReParentStyleContext, this assertion would + // If we were called from ReparentStyleContext, this assertion would // actually fire. If we need to be called from there, we can probably // just remove it; the condition probably isn't critical, although // it's worth thinking about some more. @@ -886,10 +886,10 @@ nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData) } #endif -nsReStyleHint +nsRestyleHint nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } PRBool @@ -898,10 +898,10 @@ nsTransitionManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aDat return PR_FALSE; } -nsReStyleHint +nsRestyleHint nsTransitionManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } NS_IMETHODIMP diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 373e88655fa4..680585421a43 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -92,9 +92,9 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, PRBool* aRulesChanged); diff --git a/layout/svg/base/src/nsSVGEffects.cpp b/layout/svg/base/src/nsSVGEffects.cpp index bd990bbc75e5..237c4b5a47c6 100644 --- a/layout/svg/base/src/nsSVGEffects.cpp +++ b/layout/svg/base/src/nsSVGEffects.cpp @@ -255,7 +255,7 @@ nsSVGFilterProperty::DoUpdate() NS_UpdateHint(changeHint, nsChangeHint_ReflowFrame); } mFramePresShell->FrameConstructor()->PostRestyleEvent( - mFrame->GetContent(), nsReStyleHint(0), changeHint); + mFrame->GetContent(), nsRestyleHint(0), changeHint); } void @@ -272,7 +272,7 @@ nsSVGMarkerProperty::DoUpdate() nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects); mFramePresShell->FrameConstructor()->PostRestyleEvent( - mFrame->GetContent(), nsReStyleHint(0), changeHint); + mFrame->GetContent(), nsRestyleHint(0), changeHint); } void diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 1eee1602142c..c3e4595c6cb6 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -552,7 +552,6 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState) kidFrame = kidFrame->GetNextSibling()) { nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame); if (cellFrame) { - nscoord availWidth = cellFrame->GetPriorAvailWidth(); nsSize desSize = cellFrame->GetDesiredSize(); if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !GetPrevInFlow()) { CalculateCellActualHeight(cellFrame, desSize.height); diff --git a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp index 78f8dec6c3cf..a67fcc551cbc 100644 --- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -2813,7 +2813,9 @@ nsTreeBodyFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsresult rv = nsLeafBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); NS_ENSURE_SUCCESS(rv, rv); - if (!mView) + // Bail out now if there's no view or we can't run script because the + // document is a zombie + if (!mView || !GetContent()->GetCurrentDoc()->GetScriptGlobalObject()) return NS_OK; return aLists.Content()->AppendNewToTop(new (aBuilder) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 39f7eb288673..2557f0a548f5 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -329,7 +329,7 @@ pref("extensions.spellcheck.inline.max-misspellings", 500); // belong in comm-central/editor/ui/composer.js pref("editor.use_custom_colors", false); -pref("editor.singleLine.pasteNewlines", 1); +pref("editor.singleLine.pasteNewlines", 2); pref("editor.quotesPreformatted", false); pref("editor.use_css", true); pref("editor.css.default_length_unit", "px"); @@ -2414,7 +2414,6 @@ pref("network.hosts.smtp_server", "localhost"); pref("network.hosts.pop_server", "pop"); pref("network.protocol-handler.warn-external.file", false); pref("browser.drag_out_of_frame_style", 1); -pref("editor.singleLine.pasteNewlines", 0); // Middle-mouse handling pref("middlemouse.paste", true); diff --git a/modules/plugin/test/unit/test_bug471245.js b/modules/plugin/test/unit/test_bug471245.js index d25099a742a7..9f22f658665a 100644 --- a/modules/plugin/test/unit/test_bug471245.js +++ b/modules/plugin/test/unit/test_bug471245.js @@ -60,7 +60,7 @@ function do_get_profile_startup() { throw Components.results.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIDirectoryProvider) || + if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) || iid.equals(Components.interfaces.nsISupports)) { return this; } diff --git a/parser/html/nsHtml5NamedCharacters.cpp b/parser/html/nsHtml5NamedCharacters.cpp index 13172d87276b..275a532acc9e 100644 --- a/parser/html/nsHtml5NamedCharacters.cpp +++ b/parser/html/nsHtml5NamedCharacters.cpp @@ -2,14 +2,16 @@ #include "prtypes.h" #include "jArray.h" #include "nscore.h" +#include "nsDebug.h" +#include "prlog.h" +#include "nsMemory.h" #include "nsHtml5NamedCharacters.h" jArray,PRInt32> nsHtml5NamedCharacters::NAMES; const PRUnichar nsHtml5NamedCharacters::VALUES[][2] = { - -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ { VALUE }, #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE @@ -349,31 +351,69 @@ const PRInt32* const nsHtml5NamedCharacters::HILO_ACCEL[] = { HILO_ACCEL_122 }; +/** + * To avoid having lots of pointers in the |charData| array, below, + * which would cause us to have to do lots of relocations at library + * load time, store all the string data for the names in one big array. + * Then use tricks with enums to help us build an array that contains + * the positions of each within the big arrays. + */ -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ -static PRInt8 const NAME_##N[] = { CHARS }; +static const PRInt8 ALL_NAMES[] = { +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +CHARS , #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE +}; -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ -static PRUnichar const VALUE_##N[] = { VALUE }; +enum NamePositions { + DUMMY_INITIAL_NAME_POSITION = 0, +/* enums don't take up space, so generate _START and _END */ +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +NAME_##N##_DUMMY, /* automatically one higher than previous */ \ +NAME_##N##_START = NAME_##N##_DUMMY - 1, \ +NAME_##N##_END = NAME_##N##_START + LEN + FLAG, #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE + DUMMY_FINAL_NAME_VALUE +}; -// XXX bug 501082: for some reason, msvc takes forever to optimize this function -#ifdef _MSC_VER -#pragma optimize("", off) +#define NAMED_CHARACTERS_COUNT 2138 + +/* check that the start positions will fit in 16 bits */ +PR_STATIC_ASSERT(NS_ARRAY_LENGTH(ALL_NAMES) < 0x10000); + +struct NamedCharacterData { + PRUint16 nameStart; + PRUint16 nameLen; +#ifdef DEBUG + PRInt32 n; #endif +}; + +static const NamedCharacterData charData[NAMED_CHARACTERS_COUNT] = { +#ifdef DEBUG + #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +{ NAME_##N##_START, LEN, N }, +#else + #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +{ NAME_##N##_START, LEN, }, +#endif +#include "nsHtml5NamedCharactersInclude.h" +#undef NAMED_CHARACTER_REFERENCE +}; void nsHtml5NamedCharacters::initializeStatics() { - NAMES = jArray,PRInt32>(2138); - -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ - NAMES[N] = jArray((PRInt8*)NAME_##N, LEN); -#include "nsHtml5NamedCharactersInclude.h" -#undef NAMED_CHARACTER_REFERENCE + NAMES = jArray,PRInt32>(NAMED_CHARACTERS_COUNT); + PRInt8* allNames = const_cast(ALL_NAMES); + for (PRInt32 i = 0; i < NAMED_CHARACTERS_COUNT; ++i) { + const NamedCharacterData &data = charData[i]; + NS_ABORT_IF_FALSE(data.n == i, + "index error in nsHtml5NamedCharactersInclude.h"); + NAMES[i] = jArray(allNames + data.nameStart, data.nameLen); + } WINDOWS_1252 = new PRUnichar*[32]; for (PRInt32 i = 0; i < 32; ++i) { @@ -381,10 +421,6 @@ nsHtml5NamedCharacters::initializeStatics() } } -#ifdef _MSC_VER -#pragma optimize("", on) -#endif - void nsHtml5NamedCharacters::releaseStatics() { diff --git a/parser/html/nsHtml5NamedCharacters.h b/parser/html/nsHtml5NamedCharacters.h index 8506cef3fbf2..02430a12c44b 100644 --- a/parser/html/nsHtml5NamedCharacters.h +++ b/parser/html/nsHtml5NamedCharacters.h @@ -4,6 +4,9 @@ #include "prtypes.h" #include "jArray.h" #include "nscore.h" +#include "nsDebug.h" +#include "prlog.h" +#include "nsMemory.h" class nsHtml5NamedCharacters { diff --git a/parser/html/nsHtml5NamedCharactersInclude.h b/parser/html/nsHtml5NamedCharactersInclude.h index dd849cbf5e41..b09250dded5d 100644 --- a/parser/html/nsHtml5NamedCharactersInclude.h +++ b/parser/html/nsHtml5NamedCharactersInclude.h @@ -7,9 +7,11 @@ * * 1. a unique integer N identifying the Nth [0,1,..] macro expansion in this file, * 2. a comma-separated sequence of characters comprising the character name, - * without the first two letters. See Tokenizer.java. + * without the first two letters or 0 if the sequence would be empty. + * See Tokenizer.java. * 3. the length of this sequence of characters, - * 4. a comma-separated sequence of PRUnichar literals (high to low) corresponding + * 4. placeholder flag (0 if argument #is not a placeholder and 1 if it is), + * 5. a comma-separated sequence of PRUnichar literals (high to low) corresponding * to the code-point of the named character. * * The macro expansion doesn't have to refer to all or any of these parameters, @@ -21,2143 +23,2143 @@ // split the sequence into multiple macro arguments. #define _ , -NAMED_CHARACTER_REFERENCE(0, /* A E */ 'l' _ 'i' _ 'g', 3, 0x00c6 _ 0) -NAMED_CHARACTER_REFERENCE(1, /* A E */ 'l' _ 'i' _ 'g' _ ';', 4, 0x00c6 _ 0) -NAMED_CHARACTER_REFERENCE(2, /* A M */ 'P', 1, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(3, /* A M */ 'P' _ ';', 2, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(4, /* A a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00c1 _ 0) -NAMED_CHARACTER_REFERENCE(5, /* A a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00c1 _ 0) -NAMED_CHARACTER_REFERENCE(6, /* A b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x0102 _ 0) -NAMED_CHARACTER_REFERENCE(7, /* A c */ 'i' _ 'r' _ 'c', 3, 0x00c2 _ 0) -NAMED_CHARACTER_REFERENCE(8, /* A c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00c2 _ 0) -NAMED_CHARACTER_REFERENCE(9, /* A c */ 'y' _ ';', 2, 0x0410 _ 0) -NAMED_CHARACTER_REFERENCE(10, /* A f */ 'r' _ ';', 2, 0xd835 _ 0xdd04) -NAMED_CHARACTER_REFERENCE(11, /* A g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00c0 _ 0) -NAMED_CHARACTER_REFERENCE(12, /* A g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00c0 _ 0) -NAMED_CHARACTER_REFERENCE(13, /* A l */ 'p' _ 'h' _ 'a' _ ';', 4, 0x0391 _ 0) -NAMED_CHARACTER_REFERENCE(14, /* A m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0100 _ 0) -NAMED_CHARACTER_REFERENCE(15, /* A n */ 'd' _ ';', 2, 0x2a53 _ 0) -NAMED_CHARACTER_REFERENCE(16, /* A o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0104 _ 0) -NAMED_CHARACTER_REFERENCE(17, /* A o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd38) -NAMED_CHARACTER_REFERENCE(18, /* A p */ 'p' _ 'l' _ 'y' _ 'F' _ 'u' _ 'n' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, 0x2061 _ 0) -NAMED_CHARACTER_REFERENCE(19, /* A r */ 'i' _ 'n' _ 'g', 3, 0x00c5 _ 0) -NAMED_CHARACTER_REFERENCE(20, /* A r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x00c5 _ 0) -NAMED_CHARACTER_REFERENCE(21, /* A s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdc9c) -NAMED_CHARACTER_REFERENCE(22, /* A s */ 's' _ 'i' _ 'g' _ 'n' _ ';', 5, 0x2254 _ 0) -NAMED_CHARACTER_REFERENCE(23, /* A t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00c3 _ 0) -NAMED_CHARACTER_REFERENCE(24, /* A t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00c3 _ 0) -NAMED_CHARACTER_REFERENCE(25, /* A u */ 'm' _ 'l', 2, 0x00c4 _ 0) -NAMED_CHARACTER_REFERENCE(26, /* A u */ 'm' _ 'l' _ ';', 3, 0x00c4 _ 0) -NAMED_CHARACTER_REFERENCE(27, /* B a */ 'c' _ 'k' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 8, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(28, /* B a */ 'r' _ 'v' _ ';', 3, 0x2ae7 _ 0) -NAMED_CHARACTER_REFERENCE(29, /* B a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0x2306 _ 0) -NAMED_CHARACTER_REFERENCE(30, /* B c */ 'y' _ ';', 2, 0x0411 _ 0) -NAMED_CHARACTER_REFERENCE(31, /* B e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0x2235 _ 0) -NAMED_CHARACTER_REFERENCE(32, /* B e */ 'r' _ 'n' _ 'o' _ 'u' _ 'l' _ 'l' _ 'i' _ 's' _ ';', 9, 0x212c _ 0) -NAMED_CHARACTER_REFERENCE(33, /* B e */ 't' _ 'a' _ ';', 3, 0x0392 _ 0) -NAMED_CHARACTER_REFERENCE(34, /* B f */ 'r' _ ';', 2, 0xd835 _ 0xdd05) -NAMED_CHARACTER_REFERENCE(35, /* B o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd39) -NAMED_CHARACTER_REFERENCE(36, /* B r */ 'e' _ 'v' _ 'e' _ ';', 4, 0x02d8 _ 0) -NAMED_CHARACTER_REFERENCE(37, /* B s */ 'c' _ 'r' _ ';', 3, 0x212c _ 0) -NAMED_CHARACTER_REFERENCE(38, /* B u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0x224e _ 0) -NAMED_CHARACTER_REFERENCE(39, /* C H */ 'c' _ 'y' _ ';', 3, 0x0427 _ 0) -NAMED_CHARACTER_REFERENCE(40, /* C O */ 'P' _ 'Y', 2, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(41, /* C O */ 'P' _ 'Y' _ ';', 3, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(42, /* C a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0106 _ 0) -NAMED_CHARACTER_REFERENCE(43, /* C a */ 'p' _ ';', 2, 0x22d2 _ 0) -NAMED_CHARACTER_REFERENCE(44, /* C a */ 'p' _ 'i' _ 't' _ 'a' _ 'l' _ 'D' _ 'i' _ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 19, 0x2145 _ 0) -NAMED_CHARACTER_REFERENCE(45, /* C a */ 'y' _ 'l' _ 'e' _ 'y' _ 's' _ ';', 6, 0x212d _ 0) -NAMED_CHARACTER_REFERENCE(46, /* C c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010c _ 0) -NAMED_CHARACTER_REFERENCE(47, /* C c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0x00c7 _ 0) -NAMED_CHARACTER_REFERENCE(48, /* C c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x00c7 _ 0) -NAMED_CHARACTER_REFERENCE(49, /* C c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0108 _ 0) -NAMED_CHARACTER_REFERENCE(50, /* C c */ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2230 _ 0) -NAMED_CHARACTER_REFERENCE(51, /* C d */ 'o' _ 't' _ ';', 3, 0x010a _ 0) -NAMED_CHARACTER_REFERENCE(52, /* C e */ 'd' _ 'i' _ 'l' _ 'l' _ 'a' _ ';', 6, 0x00b8 _ 0) -NAMED_CHARACTER_REFERENCE(53, /* C e */ 'n' _ 't' _ 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 8, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(54, /* C f */ 'r' _ ';', 2, 0x212d _ 0) -NAMED_CHARACTER_REFERENCE(55, /* C h */ 'i' _ ';', 2, 0x03a7 _ 0) -NAMED_CHARACTER_REFERENCE(56, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0x2299 _ 0) -NAMED_CHARACTER_REFERENCE(57, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 10, 0x2296 _ 0) -NAMED_CHARACTER_REFERENCE(58, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 9, 0x2295 _ 0) -NAMED_CHARACTER_REFERENCE(59, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 10, 0x2297 _ 0) -NAMED_CHARACTER_REFERENCE(60, /* C l */ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 23, 0x2232 _ 0) -NAMED_CHARACTER_REFERENCE(61, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 20, 0x201d _ 0) -NAMED_CHARACTER_REFERENCE(62, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 14, 0x2019 _ 0) -NAMED_CHARACTER_REFERENCE(63, /* C o */ 'l' _ 'o' _ 'n' _ ';', 4, 0x2237 _ 0) -NAMED_CHARACTER_REFERENCE(64, /* C o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0x2a74 _ 0) -NAMED_CHARACTER_REFERENCE(65, /* C o */ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 8, 0x2261 _ 0) -NAMED_CHARACTER_REFERENCE(66, /* C o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222f _ 0) -NAMED_CHARACTER_REFERENCE(67, /* C o */ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 14, 0x222e _ 0) -NAMED_CHARACTER_REFERENCE(68, /* C o */ 'p' _ 'f' _ ';', 3, 0x2102 _ 0) -NAMED_CHARACTER_REFERENCE(69, /* C o */ 'p' _ 'r' _ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 8, 0x2210 _ 0) -NAMED_CHARACTER_REFERENCE(70, /* C o */ 'u' _ 'n' _ 't' _ 'e' _ 'r' _ 'C' _ 'l' _ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 30, 0x2233 _ 0) -NAMED_CHARACTER_REFERENCE(71, /* C r */ 'o' _ 's' _ 's' _ ';', 4, 0x2a2f _ 0) -NAMED_CHARACTER_REFERENCE(72, /* C s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdc9e) -NAMED_CHARACTER_REFERENCE(73, /* C u */ 'p' _ ';', 2, 0x22d3 _ 0) -NAMED_CHARACTER_REFERENCE(74, /* C u */ 'p' _ 'C' _ 'a' _ 'p' _ ';', 5, 0x224d _ 0) -NAMED_CHARACTER_REFERENCE(75, /* D D */ ';', 1, 0x2145 _ 0) -NAMED_CHARACTER_REFERENCE(76, /* D D */ 'o' _ 't' _ 'r' _ 'a' _ 'h' _ 'd' _ ';', 7, 0x2911 _ 0) -NAMED_CHARACTER_REFERENCE(77, /* D J */ 'c' _ 'y' _ ';', 3, 0x0402 _ 0) -NAMED_CHARACTER_REFERENCE(78, /* D S */ 'c' _ 'y' _ ';', 3, 0x0405 _ 0) -NAMED_CHARACTER_REFERENCE(79, /* D Z */ 'c' _ 'y' _ ';', 3, 0x040f _ 0) -NAMED_CHARACTER_REFERENCE(80, /* D a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0x2021 _ 0) -NAMED_CHARACTER_REFERENCE(81, /* D a */ 'r' _ 'r' _ ';', 3, 0x21a1 _ 0) -NAMED_CHARACTER_REFERENCE(82, /* D a */ 's' _ 'h' _ 'v' _ ';', 4, 0x2ae4 _ 0) -NAMED_CHARACTER_REFERENCE(83, /* D c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010e _ 0) -NAMED_CHARACTER_REFERENCE(84, /* D c */ 'y' _ ';', 2, 0x0414 _ 0) -NAMED_CHARACTER_REFERENCE(85, /* D e */ 'l' _ ';', 2, 0x2207 _ 0) -NAMED_CHARACTER_REFERENCE(86, /* D e */ 'l' _ 't' _ 'a' _ ';', 4, 0x0394 _ 0) -NAMED_CHARACTER_REFERENCE(87, /* D f */ 'r' _ ';', 2, 0xd835 _ 0xdd07) -NAMED_CHARACTER_REFERENCE(88, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 15, 0x00b4 _ 0) -NAMED_CHARACTER_REFERENCE(89, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 't' _ ';', 13, 0x02d9 _ 0) -NAMED_CHARACTER_REFERENCE(90, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 21, 0x02dd _ 0) -NAMED_CHARACTER_REFERENCE(91, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'G' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 15, 0x0060 _ 0) -NAMED_CHARACTER_REFERENCE(92, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 15, 0x02dc _ 0) -NAMED_CHARACTER_REFERENCE(93, /* D i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0x22c4 _ 0) -NAMED_CHARACTER_REFERENCE(94, /* D i */ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 12, 0x2146 _ 0) -NAMED_CHARACTER_REFERENCE(95, /* D o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3b) -NAMED_CHARACTER_REFERENCE(96, /* D o */ 't' _ ';', 2, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(97, /* D o */ 't' _ 'D' _ 'o' _ 't' _ ';', 5, 0x20dc _ 0) -NAMED_CHARACTER_REFERENCE(98, /* D o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0x2250 _ 0) -NAMED_CHARACTER_REFERENCE(99, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 20, 0x222f _ 0) -NAMED_CHARACTER_REFERENCE(100, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(101, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21d3 _ 0) -NAMED_CHARACTER_REFERENCE(102, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21d0 _ 0) -NAMED_CHARACTER_REFERENCE(103, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(104, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 12, 0x2ae4 _ 0) -NAMED_CHARACTER_REFERENCE(105, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x27f8 _ 0) -NAMED_CHARACTER_REFERENCE(106, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 23, 0x27fa _ 0) -NAMED_CHARACTER_REFERENCE(107, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0x27f9 _ 0) -NAMED_CHARACTER_REFERENCE(108, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(109, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 13, 0x22a8 _ 0) -NAMED_CHARACTER_REFERENCE(110, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21d1 _ 0) -NAMED_CHARACTER_REFERENCE(111, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21d5 _ 0) -NAMED_CHARACTER_REFERENCE(112, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 16, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(113, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(114, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0x2913 _ 0) -NAMED_CHARACTER_REFERENCE(115, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21f5 _ 0) -NAMED_CHARACTER_REFERENCE(116, /* D o */ 'w' _ 'n' _ 'B' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 8, 0x0311 _ 0) -NAMED_CHARACTER_REFERENCE(117, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 18, 0x2950 _ 0) -NAMED_CHARACTER_REFERENCE(118, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0x295e _ 0) -NAMED_CHARACTER_REFERENCE(119, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0x21bd _ 0) -NAMED_CHARACTER_REFERENCE(120, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0x2956 _ 0) -NAMED_CHARACTER_REFERENCE(121, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0x295f _ 0) -NAMED_CHARACTER_REFERENCE(122, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x21c1 _ 0) -NAMED_CHARACTER_REFERENCE(123, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0x2957 _ 0) -NAMED_CHARACTER_REFERENCE(124, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ ';', 6, 0x22a4 _ 0) -NAMED_CHARACTER_REFERENCE(125, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x21a7 _ 0) -NAMED_CHARACTER_REFERENCE(126, /* D o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x21d3 _ 0) -NAMED_CHARACTER_REFERENCE(127, /* D s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdc9f) -NAMED_CHARACTER_REFERENCE(128, /* D s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0110 _ 0) -NAMED_CHARACTER_REFERENCE(129, /* E N */ 'G' _ ';', 2, 0x014a _ 0) -NAMED_CHARACTER_REFERENCE(130, /* E T */ 'H', 1, 0x00d0 _ 0) -NAMED_CHARACTER_REFERENCE(131, /* E T */ 'H' _ ';', 2, 0x00d0 _ 0) -NAMED_CHARACTER_REFERENCE(132, /* E a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00c9 _ 0) -NAMED_CHARACTER_REFERENCE(133, /* E a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00c9 _ 0) -NAMED_CHARACTER_REFERENCE(134, /* E c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x011a _ 0) -NAMED_CHARACTER_REFERENCE(135, /* E c */ 'i' _ 'r' _ 'c', 3, 0x00ca _ 0) -NAMED_CHARACTER_REFERENCE(136, /* E c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ca _ 0) -NAMED_CHARACTER_REFERENCE(137, /* E c */ 'y' _ ';', 2, 0x042d _ 0) -NAMED_CHARACTER_REFERENCE(138, /* E d */ 'o' _ 't' _ ';', 3, 0x0116 _ 0) -NAMED_CHARACTER_REFERENCE(139, /* E f */ 'r' _ ';', 2, 0xd835 _ 0xdd08) -NAMED_CHARACTER_REFERENCE(140, /* E g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00c8 _ 0) -NAMED_CHARACTER_REFERENCE(141, /* E g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00c8 _ 0) -NAMED_CHARACTER_REFERENCE(142, /* E l */ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 6, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(143, /* E m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0112 _ 0) -NAMED_CHARACTER_REFERENCE(144, /* E m */ 'p' _ 't' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 15, 0x25fb _ 0) -NAMED_CHARACTER_REFERENCE(145, /* E m */ 'p' _ 't' _ 'y' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 19, 0x25ab _ 0) -NAMED_CHARACTER_REFERENCE(146, /* E o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0118 _ 0) -NAMED_CHARACTER_REFERENCE(147, /* E o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3c) -NAMED_CHARACTER_REFERENCE(148, /* E p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x0395 _ 0) -NAMED_CHARACTER_REFERENCE(149, /* E q */ 'u' _ 'a' _ 'l' _ ';', 4, 0x2a75 _ 0) -NAMED_CHARACTER_REFERENCE(150, /* E q */ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0x2242 _ 0) -NAMED_CHARACTER_REFERENCE(151, /* E q */ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 10, 0x21cc _ 0) -NAMED_CHARACTER_REFERENCE(152, /* E s */ 'c' _ 'r' _ ';', 3, 0x2130 _ 0) -NAMED_CHARACTER_REFERENCE(153, /* E s */ 'i' _ 'm' _ ';', 3, 0x2a73 _ 0) -NAMED_CHARACTER_REFERENCE(154, /* E t */ 'a' _ ';', 2, 0x0397 _ 0) -NAMED_CHARACTER_REFERENCE(155, /* E u */ 'm' _ 'l', 2, 0x00cb _ 0) -NAMED_CHARACTER_REFERENCE(156, /* E u */ 'm' _ 'l' _ ';', 3, 0x00cb _ 0) -NAMED_CHARACTER_REFERENCE(157, /* E x */ 'i' _ 's' _ 't' _ 's' _ ';', 5, 0x2203 _ 0) -NAMED_CHARACTER_REFERENCE(158, /* E x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'E' _ ';', 11, 0x2147 _ 0) -NAMED_CHARACTER_REFERENCE(159, /* F c */ 'y' _ ';', 2, 0x0424 _ 0) -NAMED_CHARACTER_REFERENCE(160, /* F f */ 'r' _ ';', 2, 0xd835 _ 0xdd09) -NAMED_CHARACTER_REFERENCE(161, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 16, 0x25fc _ 0) -NAMED_CHARACTER_REFERENCE(162, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 20, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(163, /* F o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3d) -NAMED_CHARACTER_REFERENCE(164, /* F o */ 'r' _ 'A' _ 'l' _ 'l' _ ';', 5, 0x2200 _ 0) -NAMED_CHARACTER_REFERENCE(165, /* F o */ 'u' _ 'r' _ 'i' _ 'e' _ 'r' _ 't' _ 'r' _ 'f' _ ';', 9, 0x2131 _ 0) -NAMED_CHARACTER_REFERENCE(166, /* F s */ 'c' _ 'r' _ ';', 3, 0x2131 _ 0) -NAMED_CHARACTER_REFERENCE(167, /* G J */ 'c' _ 'y' _ ';', 3, 0x0403 _ 0) -NAMED_CHARACTER_REFERENCE(168, /* G T */ 0, 0, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(169, /* G T */ ';', 1, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(170, /* G a */ 'm' _ 'm' _ 'a' _ ';', 4, 0x0393 _ 0) -NAMED_CHARACTER_REFERENCE(171, /* G a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0x03dc _ 0) -NAMED_CHARACTER_REFERENCE(172, /* G b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x011e _ 0) -NAMED_CHARACTER_REFERENCE(173, /* G c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0122 _ 0) -NAMED_CHARACTER_REFERENCE(174, /* G c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x011c _ 0) -NAMED_CHARACTER_REFERENCE(175, /* G c */ 'y' _ ';', 2, 0x0413 _ 0) -NAMED_CHARACTER_REFERENCE(176, /* G d */ 'o' _ 't' _ ';', 3, 0x0120 _ 0) -NAMED_CHARACTER_REFERENCE(177, /* G f */ 'r' _ ';', 2, 0xd835 _ 0xdd0a) -NAMED_CHARACTER_REFERENCE(178, /* G g */ ';', 1, 0x22d9 _ 0) -NAMED_CHARACTER_REFERENCE(179, /* G o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3e) -NAMED_CHARACTER_REFERENCE(180, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0x2265 _ 0) -NAMED_CHARACTER_REFERENCE(181, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'L' _ 'e' _ 's' _ 's' _ ';', 15, 0x22db _ 0) -NAMED_CHARACTER_REFERENCE(182, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0x2267 _ 0) -NAMED_CHARACTER_REFERENCE(183, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0x2aa2 _ 0) -NAMED_CHARACTER_REFERENCE(184, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0x2277 _ 0) -NAMED_CHARACTER_REFERENCE(185, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x2a7e _ 0) -NAMED_CHARACTER_REFERENCE(186, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0x2273 _ 0) -NAMED_CHARACTER_REFERENCE(187, /* G s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca2) -NAMED_CHARACTER_REFERENCE(188, /* G t */ ';', 1, 0x226b _ 0) -NAMED_CHARACTER_REFERENCE(189, /* H A */ 'R' _ 'D' _ 'c' _ 'y' _ ';', 5, 0x042a _ 0) -NAMED_CHARACTER_REFERENCE(190, /* H a */ 'c' _ 'e' _ 'k' _ ';', 4, 0x02c7 _ 0) -NAMED_CHARACTER_REFERENCE(191, /* H a */ 't' _ ';', 2, 0x005e _ 0) -NAMED_CHARACTER_REFERENCE(192, /* H c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0124 _ 0) -NAMED_CHARACTER_REFERENCE(193, /* H f */ 'r' _ ';', 2, 0x210c _ 0) -NAMED_CHARACTER_REFERENCE(194, /* H i */ 'l' _ 'b' _ 'e' _ 'r' _ 't' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 11, 0x210b _ 0) -NAMED_CHARACTER_REFERENCE(195, /* H o */ 'p' _ 'f' _ ';', 3, 0x210d _ 0) -NAMED_CHARACTER_REFERENCE(196, /* H o */ 'r' _ 'i' _ 'z' _ 'o' _ 'n' _ 't' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 13, 0x2500 _ 0) -NAMED_CHARACTER_REFERENCE(197, /* H s */ 'c' _ 'r' _ ';', 3, 0x210b _ 0) -NAMED_CHARACTER_REFERENCE(198, /* H s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0126 _ 0) -NAMED_CHARACTER_REFERENCE(199, /* H u */ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';', 11, 0x224e _ 0) -NAMED_CHARACTER_REFERENCE(200, /* H u */ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 8, 0x224f _ 0) -NAMED_CHARACTER_REFERENCE(201, /* I E */ 'c' _ 'y' _ ';', 3, 0x0415 _ 0) -NAMED_CHARACTER_REFERENCE(202, /* I J */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0132 _ 0) -NAMED_CHARACTER_REFERENCE(203, /* I O */ 'c' _ 'y' _ ';', 3, 0x0401 _ 0) -NAMED_CHARACTER_REFERENCE(204, /* I a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00cd _ 0) -NAMED_CHARACTER_REFERENCE(205, /* I a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00cd _ 0) -NAMED_CHARACTER_REFERENCE(206, /* I c */ 'i' _ 'r' _ 'c', 3, 0x00ce _ 0) -NAMED_CHARACTER_REFERENCE(207, /* I c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ce _ 0) -NAMED_CHARACTER_REFERENCE(208, /* I c */ 'y' _ ';', 2, 0x0418 _ 0) -NAMED_CHARACTER_REFERENCE(209, /* I d */ 'o' _ 't' _ ';', 3, 0x0130 _ 0) -NAMED_CHARACTER_REFERENCE(210, /* I f */ 'r' _ ';', 2, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(211, /* I g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00cc _ 0) -NAMED_CHARACTER_REFERENCE(212, /* I g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00cc _ 0) -NAMED_CHARACTER_REFERENCE(213, /* I m */ ';', 1, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(214, /* I m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x012a _ 0) -NAMED_CHARACTER_REFERENCE(215, /* I m */ 'a' _ 'g' _ 'i' _ 'n' _ 'a' _ 'r' _ 'y' _ 'I' _ ';', 9, 0x2148 _ 0) -NAMED_CHARACTER_REFERENCE(216, /* I m */ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 6, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(217, /* I n */ 't' _ ';', 2, 0x222c _ 0) -NAMED_CHARACTER_REFERENCE(218, /* I n */ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 7, 0x222b _ 0) -NAMED_CHARACTER_REFERENCE(219, /* I n */ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 11, 0x22c2 _ 0) -NAMED_CHARACTER_REFERENCE(220, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 13, 0x2063 _ 0) -NAMED_CHARACTER_REFERENCE(221, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0x2062 _ 0) -NAMED_CHARACTER_REFERENCE(222, /* I o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x012e _ 0) -NAMED_CHARACTER_REFERENCE(223, /* I o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd40) -NAMED_CHARACTER_REFERENCE(224, /* I o */ 't' _ 'a' _ ';', 3, 0x0399 _ 0) -NAMED_CHARACTER_REFERENCE(225, /* I s */ 'c' _ 'r' _ ';', 3, 0x2110 _ 0) -NAMED_CHARACTER_REFERENCE(226, /* I t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0128 _ 0) -NAMED_CHARACTER_REFERENCE(227, /* I u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0406 _ 0) -NAMED_CHARACTER_REFERENCE(228, /* I u */ 'm' _ 'l', 2, 0x00cf _ 0) -NAMED_CHARACTER_REFERENCE(229, /* I u */ 'm' _ 'l' _ ';', 3, 0x00cf _ 0) -NAMED_CHARACTER_REFERENCE(230, /* J c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0134 _ 0) -NAMED_CHARACTER_REFERENCE(231, /* J c */ 'y' _ ';', 2, 0x0419 _ 0) -NAMED_CHARACTER_REFERENCE(232, /* J f */ 'r' _ ';', 2, 0xd835 _ 0xdd0d) -NAMED_CHARACTER_REFERENCE(233, /* J o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd41) -NAMED_CHARACTER_REFERENCE(234, /* J s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca5) -NAMED_CHARACTER_REFERENCE(235, /* J s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0x0408 _ 0) -NAMED_CHARACTER_REFERENCE(236, /* J u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0404 _ 0) -NAMED_CHARACTER_REFERENCE(237, /* K H */ 'c' _ 'y' _ ';', 3, 0x0425 _ 0) -NAMED_CHARACTER_REFERENCE(238, /* K J */ 'c' _ 'y' _ ';', 3, 0x040c _ 0) -NAMED_CHARACTER_REFERENCE(239, /* K a */ 'p' _ 'p' _ 'a' _ ';', 4, 0x039a _ 0) -NAMED_CHARACTER_REFERENCE(240, /* K c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0136 _ 0) -NAMED_CHARACTER_REFERENCE(241, /* K c */ 'y' _ ';', 2, 0x041a _ 0) -NAMED_CHARACTER_REFERENCE(242, /* K f */ 'r' _ ';', 2, 0xd835 _ 0xdd0e) -NAMED_CHARACTER_REFERENCE(243, /* K o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd42) -NAMED_CHARACTER_REFERENCE(244, /* K s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca6) -NAMED_CHARACTER_REFERENCE(245, /* L J */ 'c' _ 'y' _ ';', 3, 0x0409 _ 0) -NAMED_CHARACTER_REFERENCE(246, /* L T */ 0, 0, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(247, /* L T */ ';', 1, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(248, /* L a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0139 _ 0) -NAMED_CHARACTER_REFERENCE(249, /* L a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0x039b _ 0) -NAMED_CHARACTER_REFERENCE(250, /* L a */ 'n' _ 'g' _ ';', 3, 0x27ea _ 0) -NAMED_CHARACTER_REFERENCE(251, /* L a */ 'p' _ 'l' _ 'a' _ 'c' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 9, 0x2112 _ 0) -NAMED_CHARACTER_REFERENCE(252, /* L a */ 'r' _ 'r' _ ';', 3, 0x219e _ 0) -NAMED_CHARACTER_REFERENCE(253, /* L c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x013d _ 0) -NAMED_CHARACTER_REFERENCE(254, /* L c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x013b _ 0) -NAMED_CHARACTER_REFERENCE(255, /* L c */ 'y' _ ';', 2, 0x041b _ 0) -NAMED_CHARACTER_REFERENCE(256, /* L e */ 'f' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 15, 0x27e8 _ 0) -NAMED_CHARACTER_REFERENCE(257, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(258, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0x21e4 _ 0) -NAMED_CHARACTER_REFERENCE(259, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21c6 _ 0) -NAMED_CHARACTER_REFERENCE(260, /* L e */ 'f' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 10, 0x2308 _ 0) -NAMED_CHARACTER_REFERENCE(261, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0x27e6 _ 0) -NAMED_CHARACTER_REFERENCE(262, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0x2961 _ 0) -NAMED_CHARACTER_REFERENCE(263, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0x21c3 _ 0) -NAMED_CHARACTER_REFERENCE(264, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0x2959 _ 0) -NAMED_CHARACTER_REFERENCE(265, /* L e */ 'f' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 8, 0x230a _ 0) -NAMED_CHARACTER_REFERENCE(266, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2194 _ 0) -NAMED_CHARACTER_REFERENCE(267, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x294e _ 0) -NAMED_CHARACTER_REFERENCE(268, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 6, 0x22a3 _ 0) -NAMED_CHARACTER_REFERENCE(269, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x21a4 _ 0) -NAMED_CHARACTER_REFERENCE(270, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0x295a _ 0) -NAMED_CHARACTER_REFERENCE(271, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 11, 0x22b2 _ 0) -NAMED_CHARACTER_REFERENCE(272, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 14, 0x29cf _ 0) -NAMED_CHARACTER_REFERENCE(273, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x22b4 _ 0) -NAMED_CHARACTER_REFERENCE(274, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0x2951 _ 0) -NAMED_CHARACTER_REFERENCE(275, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x2960 _ 0) -NAMED_CHARACTER_REFERENCE(276, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 11, 0x21bf _ 0) -NAMED_CHARACTER_REFERENCE(277, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 14, 0x2958 _ 0) -NAMED_CHARACTER_REFERENCE(278, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 9, 0x21bc _ 0) -NAMED_CHARACTER_REFERENCE(279, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 12, 0x2952 _ 0) -NAMED_CHARACTER_REFERENCE(280, /* L e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x21d0 _ 0) -NAMED_CHARACTER_REFERENCE(281, /* L e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(282, /* L e */ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 15, 0x22da _ 0) -NAMED_CHARACTER_REFERENCE(283, /* L e */ 's' _ 's' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2266 _ 0) -NAMED_CHARACTER_REFERENCE(284, /* L e */ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 10, 0x2276 _ 0) -NAMED_CHARACTER_REFERENCE(285, /* L e */ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 7, 0x2aa1 _ 0) -NAMED_CHARACTER_REFERENCE(286, /* L e */ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0x2a7d _ 0) -NAMED_CHARACTER_REFERENCE(287, /* L e */ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 8, 0x2272 _ 0) -NAMED_CHARACTER_REFERENCE(288, /* L f */ 'r' _ ';', 2, 0xd835 _ 0xdd0f) -NAMED_CHARACTER_REFERENCE(289, /* L l */ ';', 1, 0x22d8 _ 0) -NAMED_CHARACTER_REFERENCE(290, /* L l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21da _ 0) -NAMED_CHARACTER_REFERENCE(291, /* L m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0x013f _ 0) -NAMED_CHARACTER_REFERENCE(292, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x27f5 _ 0) -NAMED_CHARACTER_REFERENCE(293, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x27f7 _ 0) -NAMED_CHARACTER_REFERENCE(294, /* L o */ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x27f6 _ 0) -NAMED_CHARACTER_REFERENCE(295, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x27f8 _ 0) -NAMED_CHARACTER_REFERENCE(296, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x27fa _ 0) -NAMED_CHARACTER_REFERENCE(297, /* L o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x27f9 _ 0) -NAMED_CHARACTER_REFERENCE(298, /* L o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd43) -NAMED_CHARACTER_REFERENCE(299, /* L o */ 'w' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2199 _ 0) -NAMED_CHARACTER_REFERENCE(300, /* L o */ 'w' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x2198 _ 0) -NAMED_CHARACTER_REFERENCE(301, /* L s */ 'c' _ 'r' _ ';', 3, 0x2112 _ 0) -NAMED_CHARACTER_REFERENCE(302, /* L s */ 'h' _ ';', 2, 0x21b0 _ 0) -NAMED_CHARACTER_REFERENCE(303, /* L s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0141 _ 0) -NAMED_CHARACTER_REFERENCE(304, /* L t */ ';', 1, 0x226a _ 0) -NAMED_CHARACTER_REFERENCE(305, /* M a */ 'p' _ ';', 2, 0x2905 _ 0) -NAMED_CHARACTER_REFERENCE(306, /* M c */ 'y' _ ';', 2, 0x041c _ 0) -NAMED_CHARACTER_REFERENCE(307, /* M e */ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 10, 0x205f _ 0) -NAMED_CHARACTER_REFERENCE(308, /* M e */ 'l' _ 'l' _ 'i' _ 'n' _ 't' _ 'r' _ 'f' _ ';', 8, 0x2133 _ 0) -NAMED_CHARACTER_REFERENCE(309, /* M f */ 'r' _ ';', 2, 0xd835 _ 0xdd10) -NAMED_CHARACTER_REFERENCE(310, /* M i */ 'n' _ 'u' _ 's' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2213 _ 0) -NAMED_CHARACTER_REFERENCE(311, /* M o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd44) -NAMED_CHARACTER_REFERENCE(312, /* M s */ 'c' _ 'r' _ ';', 3, 0x2133 _ 0) -NAMED_CHARACTER_REFERENCE(313, /* M u */ ';', 1, 0x039c _ 0) -NAMED_CHARACTER_REFERENCE(314, /* N J */ 'c' _ 'y' _ ';', 3, 0x040a _ 0) -NAMED_CHARACTER_REFERENCE(315, /* N a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0143 _ 0) -NAMED_CHARACTER_REFERENCE(316, /* N c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0147 _ 0) -NAMED_CHARACTER_REFERENCE(317, /* N c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0145 _ 0) -NAMED_CHARACTER_REFERENCE(318, /* N c */ 'y' _ ';', 2, 0x041d _ 0) -NAMED_CHARACTER_REFERENCE(319, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'M' _ 'e' _ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 18, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(320, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 17, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(321, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 16, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(322, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'V' _ 'e' _ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 20, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(323, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 19, 0x226b _ 0) -NAMED_CHARACTER_REFERENCE(324, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0x226a _ 0) -NAMED_CHARACTER_REFERENCE(325, /* N e */ 'w' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 6, 0x000a _ 0) -NAMED_CHARACTER_REFERENCE(326, /* N f */ 'r' _ ';', 2, 0xd835 _ 0xdd11) -NAMED_CHARACTER_REFERENCE(327, /* N o */ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ ';', 6, 0x2060 _ 0) -NAMED_CHARACTER_REFERENCE(328, /* N o */ 'n' _ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ 'i' _ 'n' _ 'g' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 15, 0x00a0 _ 0) -NAMED_CHARACTER_REFERENCE(329, /* N o */ 'p' _ 'f' _ ';', 3, 0x2115 _ 0) -NAMED_CHARACTER_REFERENCE(330, /* N o */ 't' _ ';', 2, 0x2aec _ 0) -NAMED_CHARACTER_REFERENCE(331, /* N o */ 't' _ 'C' _ 'o' _ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 11, 0x2262 _ 0) -NAMED_CHARACTER_REFERENCE(332, /* N o */ 't' _ 'C' _ 'u' _ 'p' _ 'C' _ 'a' _ 'p' _ ';', 8, 0x226d _ 0) -NAMED_CHARACTER_REFERENCE(333, /* N o */ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 19, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(334, /* N o */ 't' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0x2209 _ 0) -NAMED_CHARACTER_REFERENCE(335, /* N o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0x2260 _ 0) -NAMED_CHARACTER_REFERENCE(336, /* N o */ 't' _ 'E' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0x2204 _ 0) -NAMED_CHARACTER_REFERENCE(337, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 9, 0x226f _ 0) -NAMED_CHARACTER_REFERENCE(338, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 14, 0x2271 _ 0) -NAMED_CHARACTER_REFERENCE(339, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0x2279 _ 0) -NAMED_CHARACTER_REFERENCE(340, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 14, 0x2275 _ 0) -NAMED_CHARACTER_REFERENCE(341, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 14, 0x22ea _ 0) -NAMED_CHARACTER_REFERENCE(342, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0x22ec _ 0) -NAMED_CHARACTER_REFERENCE(343, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ ';', 6, 0x226e _ 0) -NAMED_CHARACTER_REFERENCE(344, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0x2270 _ 0) -NAMED_CHARACTER_REFERENCE(345, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0x2278 _ 0) -NAMED_CHARACTER_REFERENCE(346, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0x2274 _ 0) -NAMED_CHARACTER_REFERENCE(347, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 10, 0x2280 _ 0) -NAMED_CHARACTER_REFERENCE(348, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0x22e0 _ 0) -NAMED_CHARACTER_REFERENCE(349, /* N o */ 't' _ 'R' _ 'e' _ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 16, 0x220c _ 0) -NAMED_CHARACTER_REFERENCE(350, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 15, 0x22eb _ 0) -NAMED_CHARACTER_REFERENCE(351, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0x22ed _ 0) -NAMED_CHARACTER_REFERENCE(352, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0x22e2 _ 0) -NAMED_CHARACTER_REFERENCE(353, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 21, 0x22e3 _ 0) -NAMED_CHARACTER_REFERENCE(354, /* N o */ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0x2288 _ 0) -NAMED_CHARACTER_REFERENCE(355, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 10, 0x2281 _ 0) -NAMED_CHARACTER_REFERENCE(356, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0x22e1 _ 0) -NAMED_CHARACTER_REFERENCE(357, /* N o */ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0x2289 _ 0) -NAMED_CHARACTER_REFERENCE(358, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x2241 _ 0) -NAMED_CHARACTER_REFERENCE(359, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2244 _ 0) -NAMED_CHARACTER_REFERENCE(360, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x2247 _ 0) -NAMED_CHARACTER_REFERENCE(361, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x2249 _ 0) -NAMED_CHARACTER_REFERENCE(362, /* N o */ 't' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 13, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(363, /* N s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca9) -NAMED_CHARACTER_REFERENCE(364, /* N t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00d1 _ 0) -NAMED_CHARACTER_REFERENCE(365, /* N t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00d1 _ 0) -NAMED_CHARACTER_REFERENCE(366, /* N u */ ';', 1, 0x039d _ 0) -NAMED_CHARACTER_REFERENCE(367, /* O E */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0152 _ 0) -NAMED_CHARACTER_REFERENCE(368, /* O a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00d3 _ 0) -NAMED_CHARACTER_REFERENCE(369, /* O a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00d3 _ 0) -NAMED_CHARACTER_REFERENCE(370, /* O c */ 'i' _ 'r' _ 'c', 3, 0x00d4 _ 0) -NAMED_CHARACTER_REFERENCE(371, /* O c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00d4 _ 0) -NAMED_CHARACTER_REFERENCE(372, /* O c */ 'y' _ ';', 2, 0x041e _ 0) -NAMED_CHARACTER_REFERENCE(373, /* O d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0150 _ 0) -NAMED_CHARACTER_REFERENCE(374, /* O f */ 'r' _ ';', 2, 0xd835 _ 0xdd12) -NAMED_CHARACTER_REFERENCE(375, /* O g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00d2 _ 0) -NAMED_CHARACTER_REFERENCE(376, /* O g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00d2 _ 0) -NAMED_CHARACTER_REFERENCE(377, /* O m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x014c _ 0) -NAMED_CHARACTER_REFERENCE(378, /* O m */ 'e' _ 'g' _ 'a' _ ';', 4, 0x03a9 _ 0) -NAMED_CHARACTER_REFERENCE(379, /* O m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0x039f _ 0) -NAMED_CHARACTER_REFERENCE(380, /* O o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd46) -NAMED_CHARACTER_REFERENCE(381, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 19, 0x201c _ 0) -NAMED_CHARACTER_REFERENCE(382, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 13, 0x2018 _ 0) -NAMED_CHARACTER_REFERENCE(383, /* O r */ ';', 1, 0x2a54 _ 0) -NAMED_CHARACTER_REFERENCE(384, /* O s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcaa) -NAMED_CHARACTER_REFERENCE(385, /* O s */ 'l' _ 'a' _ 's' _ 'h', 4, 0x00d8 _ 0) -NAMED_CHARACTER_REFERENCE(386, /* O s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0x00d8 _ 0) -NAMED_CHARACTER_REFERENCE(387, /* O t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00d5 _ 0) -NAMED_CHARACTER_REFERENCE(388, /* O t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00d5 _ 0) -NAMED_CHARACTER_REFERENCE(389, /* O t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x2a37 _ 0) -NAMED_CHARACTER_REFERENCE(390, /* O u */ 'm' _ 'l', 2, 0x00d6 _ 0) -NAMED_CHARACTER_REFERENCE(391, /* O u */ 'm' _ 'l' _ ';', 3, 0x00d6 _ 0) -NAMED_CHARACTER_REFERENCE(392, /* O v */ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 6, 0x203e _ 0) -NAMED_CHARACTER_REFERENCE(393, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 8, 0x23de _ 0) -NAMED_CHARACTER_REFERENCE(394, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 10, 0x23b4 _ 0) -NAMED_CHARACTER_REFERENCE(395, /* O v */ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 14, 0x23dc _ 0) -NAMED_CHARACTER_REFERENCE(396, /* P a */ 'r' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 7, 0x2202 _ 0) -NAMED_CHARACTER_REFERENCE(397, /* P c */ 'y' _ ';', 2, 0x041f _ 0) -NAMED_CHARACTER_REFERENCE(398, /* P f */ 'r' _ ';', 2, 0xd835 _ 0xdd13) -NAMED_CHARACTER_REFERENCE(399, /* P h */ 'i' _ ';', 2, 0x03a6 _ 0) -NAMED_CHARACTER_REFERENCE(400, /* P i */ ';', 1, 0x03a0 _ 0) -NAMED_CHARACTER_REFERENCE(401, /* P l */ 'u' _ 's' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 8, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(402, /* P o */ 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ 'p' _ 'l' _ 'a' _ 'n' _ 'e' _ ';', 12, 0x210c _ 0) -NAMED_CHARACTER_REFERENCE(403, /* P o */ 'p' _ 'f' _ ';', 3, 0x2119 _ 0) -NAMED_CHARACTER_REFERENCE(404, /* P r */ ';', 1, 0x2abb _ 0) -NAMED_CHARACTER_REFERENCE(405, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 7, 0x227a _ 0) -NAMED_CHARACTER_REFERENCE(406, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2aaf _ 0) -NAMED_CHARACTER_REFERENCE(407, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0x227c _ 0) -NAMED_CHARACTER_REFERENCE(408, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x227e _ 0) -NAMED_CHARACTER_REFERENCE(409, /* P r */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2033 _ 0) -NAMED_CHARACTER_REFERENCE(410, /* P r */ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 6, 0x220f _ 0) -NAMED_CHARACTER_REFERENCE(411, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 9, 0x2237 _ 0) -NAMED_CHARACTER_REFERENCE(412, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ ';', 11, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(413, /* P s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcab) -NAMED_CHARACTER_REFERENCE(414, /* P s */ 'i' _ ';', 2, 0x03a8 _ 0) -NAMED_CHARACTER_REFERENCE(415, /* Q U */ 'O' _ 'T', 2, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(416, /* Q U */ 'O' _ 'T' _ ';', 3, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(417, /* Q f */ 'r' _ ';', 2, 0xd835 _ 0xdd14) -NAMED_CHARACTER_REFERENCE(418, /* Q o */ 'p' _ 'f' _ ';', 3, 0x211a _ 0) -NAMED_CHARACTER_REFERENCE(419, /* Q s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcac) -NAMED_CHARACTER_REFERENCE(420, /* R B */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2910 _ 0) -NAMED_CHARACTER_REFERENCE(421, /* R E */ 'G', 1, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(422, /* R E */ 'G' _ ';', 2, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(423, /* R a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0154 _ 0) -NAMED_CHARACTER_REFERENCE(424, /* R a */ 'n' _ 'g' _ ';', 3, 0x27eb _ 0) -NAMED_CHARACTER_REFERENCE(425, /* R a */ 'r' _ 'r' _ ';', 3, 0x21a0 _ 0) -NAMED_CHARACTER_REFERENCE(426, /* R a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0x2916 _ 0) -NAMED_CHARACTER_REFERENCE(427, /* R c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0158 _ 0) -NAMED_CHARACTER_REFERENCE(428, /* R c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0156 _ 0) -NAMED_CHARACTER_REFERENCE(429, /* R c */ 'y' _ ';', 2, 0x0420 _ 0) -NAMED_CHARACTER_REFERENCE(430, /* R e */ ';', 1, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(431, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 13, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(432, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 17, 0x21cb _ 0) -NAMED_CHARACTER_REFERENCE(433, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'U' _ 'p' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 19, 0x296f _ 0) -NAMED_CHARACTER_REFERENCE(434, /* R f */ 'r' _ ';', 2, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(435, /* R h */ 'o' _ ';', 2, 0x03a1 _ 0) -NAMED_CHARACTER_REFERENCE(436, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0x27e9 _ 0) -NAMED_CHARACTER_REFERENCE(437, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(438, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 12, 0x21e5 _ 0) -NAMED_CHARACTER_REFERENCE(439, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21c4 _ 0) -NAMED_CHARACTER_REFERENCE(440, /* R i */ 'g' _ 'h' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 11, 0x2309 _ 0) -NAMED_CHARACTER_REFERENCE(441, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 17, 0x27e7 _ 0) -NAMED_CHARACTER_REFERENCE(442, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0x295d _ 0) -NAMED_CHARACTER_REFERENCE(443, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x21c2 _ 0) -NAMED_CHARACTER_REFERENCE(444, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0x2955 _ 0) -NAMED_CHARACTER_REFERENCE(445, /* R i */ 'g' _ 'h' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 9, 0x230b _ 0) -NAMED_CHARACTER_REFERENCE(446, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 7, 0x22a2 _ 0) -NAMED_CHARACTER_REFERENCE(447, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21a6 _ 0) -NAMED_CHARACTER_REFERENCE(448, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0x295b _ 0) -NAMED_CHARACTER_REFERENCE(449, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0x22b3 _ 0) -NAMED_CHARACTER_REFERENCE(450, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 15, 0x29d0 _ 0) -NAMED_CHARACTER_REFERENCE(451, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0x22b5 _ 0) -NAMED_CHARACTER_REFERENCE(452, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0x294f _ 0) -NAMED_CHARACTER_REFERENCE(453, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0x295c _ 0) -NAMED_CHARACTER_REFERENCE(454, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0x21be _ 0) -NAMED_CHARACTER_REFERENCE(455, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 15, 0x2954 _ 0) -NAMED_CHARACTER_REFERENCE(456, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 10, 0x21c0 _ 0) -NAMED_CHARACTER_REFERENCE(457, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 13, 0x2953 _ 0) -NAMED_CHARACTER_REFERENCE(458, /* R i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(459, /* R o */ 'p' _ 'f' _ ';', 3, 0x211d _ 0) -NAMED_CHARACTER_REFERENCE(460, /* R o */ 'u' _ 'n' _ 'd' _ 'I' _ 'm' _ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 11, 0x2970 _ 0) -NAMED_CHARACTER_REFERENCE(461, /* R r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x21db _ 0) -NAMED_CHARACTER_REFERENCE(462, /* R s */ 'c' _ 'r' _ ';', 3, 0x211b _ 0) -NAMED_CHARACTER_REFERENCE(463, /* R s */ 'h' _ ';', 2, 0x21b1 _ 0) -NAMED_CHARACTER_REFERENCE(464, /* R u */ 'l' _ 'e' _ 'D' _ 'e' _ 'l' _ 'a' _ 'y' _ 'e' _ 'd' _ ';', 10, 0x29f4 _ 0) -NAMED_CHARACTER_REFERENCE(465, /* S H */ 'C' _ 'H' _ 'c' _ 'y' _ ';', 5, 0x0429 _ 0) -NAMED_CHARACTER_REFERENCE(466, /* S H */ 'c' _ 'y' _ ';', 3, 0x0428 _ 0) -NAMED_CHARACTER_REFERENCE(467, /* S O */ 'F' _ 'T' _ 'c' _ 'y' _ ';', 5, 0x042c _ 0) -NAMED_CHARACTER_REFERENCE(468, /* S a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x015a _ 0) -NAMED_CHARACTER_REFERENCE(469, /* S c */ ';', 1, 0x2abc _ 0) -NAMED_CHARACTER_REFERENCE(470, /* S c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0160 _ 0) -NAMED_CHARACTER_REFERENCE(471, /* S c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x015e _ 0) -NAMED_CHARACTER_REFERENCE(472, /* S c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x015c _ 0) -NAMED_CHARACTER_REFERENCE(473, /* S c */ 'y' _ ';', 2, 0x0421 _ 0) -NAMED_CHARACTER_REFERENCE(474, /* S f */ 'r' _ ';', 2, 0xd835 _ 0xdd16) -NAMED_CHARACTER_REFERENCE(475, /* S h */ 'o' _ 'r' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(476, /* S h */ 'o' _ 'r' _ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(477, /* S h */ 'o' _ 'r' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(478, /* S h */ 'o' _ 'r' _ 't' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(479, /* S i */ 'g' _ 'm' _ 'a' _ ';', 4, 0x03a3 _ 0) -NAMED_CHARACTER_REFERENCE(480, /* S m */ 'a' _ 'l' _ 'l' _ 'C' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ ';', 10, 0x2218 _ 0) -NAMED_CHARACTER_REFERENCE(481, /* S o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4a) -NAMED_CHARACTER_REFERENCE(482, /* S q */ 'r' _ 't' _ ';', 3, 0x221a _ 0) -NAMED_CHARACTER_REFERENCE(483, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0x25a1 _ 0) -NAMED_CHARACTER_REFERENCE(484, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'I' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 17, 0x2293 _ 0) -NAMED_CHARACTER_REFERENCE(485, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 11, 0x228f _ 0) -NAMED_CHARACTER_REFERENCE(486, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x2291 _ 0) -NAMED_CHARACTER_REFERENCE(487, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 13, 0x2290 _ 0) -NAMED_CHARACTER_REFERENCE(488, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 18, 0x2292 _ 0) -NAMED_CHARACTER_REFERENCE(489, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'U' _ 'n' _ 'i' _ 'o' _ 'n' _ ';', 10, 0x2294 _ 0) -NAMED_CHARACTER_REFERENCE(490, /* S s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcae) -NAMED_CHARACTER_REFERENCE(491, /* S t */ 'a' _ 'r' _ ';', 3, 0x22c6 _ 0) -NAMED_CHARACTER_REFERENCE(492, /* S u */ 'b' _ ';', 2, 0x22d0 _ 0) -NAMED_CHARACTER_REFERENCE(493, /* S u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0x22d0 _ 0) -NAMED_CHARACTER_REFERENCE(494, /* S u */ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 10, 0x2286 _ 0) -NAMED_CHARACTER_REFERENCE(495, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 7, 0x227b _ 0) -NAMED_CHARACTER_REFERENCE(496, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2ab0 _ 0) -NAMED_CHARACTER_REFERENCE(497, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0x227d _ 0) -NAMED_CHARACTER_REFERENCE(498, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x227f _ 0) -NAMED_CHARACTER_REFERENCE(499, /* S u */ 'c' _ 'h' _ 'T' _ 'h' _ 'a' _ 't' _ ';', 7, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(500, /* S u */ 'm' _ ';', 2, 0x2211 _ 0) -NAMED_CHARACTER_REFERENCE(501, /* S u */ 'p' _ ';', 2, 0x22d1 _ 0) -NAMED_CHARACTER_REFERENCE(502, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 7, 0x2283 _ 0) -NAMED_CHARACTER_REFERENCE(503, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2287 _ 0) -NAMED_CHARACTER_REFERENCE(504, /* S u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0x22d1 _ 0) -NAMED_CHARACTER_REFERENCE(505, /* T H */ 'O' _ 'R' _ 'N', 3, 0x00de _ 0) -NAMED_CHARACTER_REFERENCE(506, /* T H */ 'O' _ 'R' _ 'N' _ ';', 4, 0x00de _ 0) -NAMED_CHARACTER_REFERENCE(507, /* T R */ 'A' _ 'D' _ 'E' _ ';', 4, 0x2122 _ 0) -NAMED_CHARACTER_REFERENCE(508, /* T S */ 'H' _ 'c' _ 'y' _ ';', 4, 0x040b _ 0) -NAMED_CHARACTER_REFERENCE(509, /* T S */ 'c' _ 'y' _ ';', 3, 0x0426 _ 0) -NAMED_CHARACTER_REFERENCE(510, /* T a */ 'b' _ ';', 2, 0x0009 _ 0) -NAMED_CHARACTER_REFERENCE(511, /* T a */ 'u' _ ';', 2, 0x03a4 _ 0) -NAMED_CHARACTER_REFERENCE(512, /* T c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0164 _ 0) -NAMED_CHARACTER_REFERENCE(513, /* T c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0162 _ 0) -NAMED_CHARACTER_REFERENCE(514, /* T c */ 'y' _ ';', 2, 0x0422 _ 0) -NAMED_CHARACTER_REFERENCE(515, /* T f */ 'r' _ ';', 2, 0xd835 _ 0xdd17) -NAMED_CHARACTER_REFERENCE(516, /* T h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0x2234 _ 0) -NAMED_CHARACTER_REFERENCE(517, /* T h */ 'e' _ 't' _ 'a' _ ';', 4, 0x0398 _ 0) -NAMED_CHARACTER_REFERENCE(518, /* T h */ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 8, 0x2009 _ 0) -NAMED_CHARACTER_REFERENCE(519, /* T i */ 'l' _ 'd' _ 'e' _ ';', 4, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(520, /* T i */ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 9, 0x2243 _ 0) -NAMED_CHARACTER_REFERENCE(521, /* T i */ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0x2245 _ 0) -NAMED_CHARACTER_REFERENCE(522, /* T i */ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(523, /* T o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4b) -NAMED_CHARACTER_REFERENCE(524, /* T r */ 'i' _ 'p' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0x20db _ 0) -NAMED_CHARACTER_REFERENCE(525, /* T s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcaf) -NAMED_CHARACTER_REFERENCE(526, /* T s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0166 _ 0) -NAMED_CHARACTER_REFERENCE(527, /* U a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00da _ 0) -NAMED_CHARACTER_REFERENCE(528, /* U a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00da _ 0) -NAMED_CHARACTER_REFERENCE(529, /* U a */ 'r' _ 'r' _ ';', 3, 0x219f _ 0) -NAMED_CHARACTER_REFERENCE(530, /* U a */ 'r' _ 'r' _ 'o' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2949 _ 0) -NAMED_CHARACTER_REFERENCE(531, /* U b */ 'r' _ 'c' _ 'y' _ ';', 4, 0x040e _ 0) -NAMED_CHARACTER_REFERENCE(532, /* U b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x016c _ 0) -NAMED_CHARACTER_REFERENCE(533, /* U c */ 'i' _ 'r' _ 'c', 3, 0x00db _ 0) -NAMED_CHARACTER_REFERENCE(534, /* U c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00db _ 0) -NAMED_CHARACTER_REFERENCE(535, /* U c */ 'y' _ ';', 2, 0x0423 _ 0) -NAMED_CHARACTER_REFERENCE(536, /* U d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0170 _ 0) -NAMED_CHARACTER_REFERENCE(537, /* U f */ 'r' _ ';', 2, 0xd835 _ 0xdd18) -NAMED_CHARACTER_REFERENCE(538, /* U g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00d9 _ 0) -NAMED_CHARACTER_REFERENCE(539, /* U g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00d9 _ 0) -NAMED_CHARACTER_REFERENCE(540, /* U m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x016a _ 0) -NAMED_CHARACTER_REFERENCE(541, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 7, 0x005f _ 0) -NAMED_CHARACTER_REFERENCE(542, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 9, 0x23df _ 0) -NAMED_CHARACTER_REFERENCE(543, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 11, 0x23b5 _ 0) -NAMED_CHARACTER_REFERENCE(544, /* U n */ 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 15, 0x23dd _ 0) -NAMED_CHARACTER_REFERENCE(545, /* U n */ 'i' _ 'o' _ 'n' _ ';', 4, 0x22c3 _ 0) -NAMED_CHARACTER_REFERENCE(546, /* U n */ 'i' _ 'o' _ 'n' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0x228e _ 0) -NAMED_CHARACTER_REFERENCE(547, /* U o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0172 _ 0) -NAMED_CHARACTER_REFERENCE(548, /* U o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4c) -NAMED_CHARACTER_REFERENCE(549, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(550, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 9, 0x2912 _ 0) -NAMED_CHARACTER_REFERENCE(551, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21c5 _ 0) -NAMED_CHARACTER_REFERENCE(552, /* U p */ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2195 _ 0) -NAMED_CHARACTER_REFERENCE(553, /* U p */ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 12, 0x296e _ 0) -NAMED_CHARACTER_REFERENCE(554, /* U p */ 'T' _ 'e' _ 'e' _ ';', 4, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(555, /* U p */ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21a5 _ 0) -NAMED_CHARACTER_REFERENCE(556, /* U p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x21d1 _ 0) -NAMED_CHARACTER_REFERENCE(557, /* U p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x21d5 _ 0) -NAMED_CHARACTER_REFERENCE(558, /* U p */ 'p' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2196 _ 0) -NAMED_CHARACTER_REFERENCE(559, /* U p */ 'p' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x2197 _ 0) -NAMED_CHARACTER_REFERENCE(560, /* U p */ 's' _ 'i' _ ';', 3, 0x03d2 _ 0) -NAMED_CHARACTER_REFERENCE(561, /* U p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x03a5 _ 0) -NAMED_CHARACTER_REFERENCE(562, /* U r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x016e _ 0) -NAMED_CHARACTER_REFERENCE(563, /* U s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb0) -NAMED_CHARACTER_REFERENCE(564, /* U t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0168 _ 0) -NAMED_CHARACTER_REFERENCE(565, /* U u */ 'm' _ 'l', 2, 0x00dc _ 0) -NAMED_CHARACTER_REFERENCE(566, /* U u */ 'm' _ 'l' _ ';', 3, 0x00dc _ 0) -NAMED_CHARACTER_REFERENCE(567, /* V D */ 'a' _ 's' _ 'h' _ ';', 4, 0x22ab _ 0) -NAMED_CHARACTER_REFERENCE(568, /* V b */ 'a' _ 'r' _ ';', 3, 0x2aeb _ 0) -NAMED_CHARACTER_REFERENCE(569, /* V c */ 'y' _ ';', 2, 0x0412 _ 0) -NAMED_CHARACTER_REFERENCE(570, /* V d */ 'a' _ 's' _ 'h' _ ';', 4, 0x22a9 _ 0) -NAMED_CHARACTER_REFERENCE(571, /* V d */ 'a' _ 's' _ 'h' _ 'l' _ ';', 5, 0x2ae6 _ 0) -NAMED_CHARACTER_REFERENCE(572, /* V e */ 'e' _ ';', 2, 0x22c1 _ 0) -NAMED_CHARACTER_REFERENCE(573, /* V e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x2016 _ 0) -NAMED_CHARACTER_REFERENCE(574, /* V e */ 'r' _ 't' _ ';', 3, 0x2016 _ 0) -NAMED_CHARACTER_REFERENCE(575, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 10, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(576, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 11, 0x007c _ 0) -NAMED_CHARACTER_REFERENCE(577, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'S' _ 'e' _ 'p' _ 'a' _ 'r' _ 'a' _ 't' _ 'o' _ 'r' _ ';', 16, 0x2758 _ 0) -NAMED_CHARACTER_REFERENCE(578, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x2240 _ 0) -NAMED_CHARACTER_REFERENCE(579, /* V e */ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 12, 0x200a _ 0) -NAMED_CHARACTER_REFERENCE(580, /* V f */ 'r' _ ';', 2, 0xd835 _ 0xdd19) -NAMED_CHARACTER_REFERENCE(581, /* V o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4d) -NAMED_CHARACTER_REFERENCE(582, /* V s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb1) -NAMED_CHARACTER_REFERENCE(583, /* V v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22aa _ 0) -NAMED_CHARACTER_REFERENCE(584, /* W c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0174 _ 0) -NAMED_CHARACTER_REFERENCE(585, /* W e */ 'd' _ 'g' _ 'e' _ ';', 4, 0x22c0 _ 0) -NAMED_CHARACTER_REFERENCE(586, /* W f */ 'r' _ ';', 2, 0xd835 _ 0xdd1a) -NAMED_CHARACTER_REFERENCE(587, /* W o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4e) -NAMED_CHARACTER_REFERENCE(588, /* W s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb2) -NAMED_CHARACTER_REFERENCE(589, /* X f */ 'r' _ ';', 2, 0xd835 _ 0xdd1b) -NAMED_CHARACTER_REFERENCE(590, /* X i */ ';', 1, 0x039e _ 0) -NAMED_CHARACTER_REFERENCE(591, /* X o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4f) -NAMED_CHARACTER_REFERENCE(592, /* X s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb3) -NAMED_CHARACTER_REFERENCE(593, /* Y A */ 'c' _ 'y' _ ';', 3, 0x042f _ 0) -NAMED_CHARACTER_REFERENCE(594, /* Y I */ 'c' _ 'y' _ ';', 3, 0x0407 _ 0) -NAMED_CHARACTER_REFERENCE(595, /* Y U */ 'c' _ 'y' _ ';', 3, 0x042e _ 0) -NAMED_CHARACTER_REFERENCE(596, /* Y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00dd _ 0) -NAMED_CHARACTER_REFERENCE(597, /* Y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00dd _ 0) -NAMED_CHARACTER_REFERENCE(598, /* Y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0176 _ 0) -NAMED_CHARACTER_REFERENCE(599, /* Y c */ 'y' _ ';', 2, 0x042b _ 0) -NAMED_CHARACTER_REFERENCE(600, /* Y f */ 'r' _ ';', 2, 0xd835 _ 0xdd1c) -NAMED_CHARACTER_REFERENCE(601, /* Y o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd50) -NAMED_CHARACTER_REFERENCE(602, /* Y s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb4) -NAMED_CHARACTER_REFERENCE(603, /* Y u */ 'm' _ 'l' _ ';', 3, 0x0178 _ 0) -NAMED_CHARACTER_REFERENCE(604, /* Z H */ 'c' _ 'y' _ ';', 3, 0x0416 _ 0) -NAMED_CHARACTER_REFERENCE(605, /* Z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0179 _ 0) -NAMED_CHARACTER_REFERENCE(606, /* Z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x017d _ 0) -NAMED_CHARACTER_REFERENCE(607, /* Z c */ 'y' _ ';', 2, 0x0417 _ 0) -NAMED_CHARACTER_REFERENCE(608, /* Z d */ 'o' _ 't' _ ';', 3, 0x017b _ 0) -NAMED_CHARACTER_REFERENCE(609, /* Z e */ 'r' _ 'o' _ 'W' _ 'i' _ 'd' _ 't' _ 'h' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 13, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(610, /* Z e */ 't' _ 'a' _ ';', 3, 0x0396 _ 0) -NAMED_CHARACTER_REFERENCE(611, /* Z f */ 'r' _ ';', 2, 0x2128 _ 0) -NAMED_CHARACTER_REFERENCE(612, /* Z o */ 'p' _ 'f' _ ';', 3, 0x2124 _ 0) -NAMED_CHARACTER_REFERENCE(613, /* Z s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb5) -NAMED_CHARACTER_REFERENCE(614, /* a a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00e1 _ 0) -NAMED_CHARACTER_REFERENCE(615, /* a a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00e1 _ 0) -NAMED_CHARACTER_REFERENCE(616, /* a b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x0103 _ 0) -NAMED_CHARACTER_REFERENCE(617, /* a c */ ';', 1, 0x223e _ 0) -NAMED_CHARACTER_REFERENCE(618, /* a c */ 'd' _ ';', 2, 0x223f _ 0) -NAMED_CHARACTER_REFERENCE(619, /* a c */ 'i' _ 'r' _ 'c', 3, 0x00e2 _ 0) -NAMED_CHARACTER_REFERENCE(620, /* a c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00e2 _ 0) -NAMED_CHARACTER_REFERENCE(621, /* a c */ 'u' _ 't' _ 'e', 3, 0x00b4 _ 0) -NAMED_CHARACTER_REFERENCE(622, /* a c */ 'u' _ 't' _ 'e' _ ';', 4, 0x00b4 _ 0) -NAMED_CHARACTER_REFERENCE(623, /* a c */ 'y' _ ';', 2, 0x0430 _ 0) -NAMED_CHARACTER_REFERENCE(624, /* a e */ 'l' _ 'i' _ 'g', 3, 0x00e6 _ 0) -NAMED_CHARACTER_REFERENCE(625, /* a e */ 'l' _ 'i' _ 'g' _ ';', 4, 0x00e6 _ 0) -NAMED_CHARACTER_REFERENCE(626, /* a f */ ';', 1, 0x2061 _ 0) -NAMED_CHARACTER_REFERENCE(627, /* a f */ 'r' _ ';', 2, 0xd835 _ 0xdd1e) -NAMED_CHARACTER_REFERENCE(628, /* a g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00e0 _ 0) -NAMED_CHARACTER_REFERENCE(629, /* a g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00e0 _ 0) -NAMED_CHARACTER_REFERENCE(630, /* a l */ 'e' _ 'f' _ 's' _ 'y' _ 'm' _ ';', 6, 0x2135 _ 0) -NAMED_CHARACTER_REFERENCE(631, /* a l */ 'e' _ 'p' _ 'h' _ ';', 4, 0x2135 _ 0) -NAMED_CHARACTER_REFERENCE(632, /* a l */ 'p' _ 'h' _ 'a' _ ';', 4, 0x03b1 _ 0) -NAMED_CHARACTER_REFERENCE(633, /* a m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0101 _ 0) -NAMED_CHARACTER_REFERENCE(634, /* a m */ 'a' _ 'l' _ 'g' _ ';', 4, 0x2a3f _ 0) -NAMED_CHARACTER_REFERENCE(635, /* a m */ 'p', 1, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(636, /* a m */ 'p' _ ';', 2, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(637, /* a n */ 'd' _ ';', 2, 0x2227 _ 0) -NAMED_CHARACTER_REFERENCE(638, /* a n */ 'd' _ 'a' _ 'n' _ 'd' _ ';', 5, 0x2a55 _ 0) -NAMED_CHARACTER_REFERENCE(639, /* a n */ 'd' _ 'd' _ ';', 3, 0x2a5c _ 0) -NAMED_CHARACTER_REFERENCE(640, /* a n */ 'd' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 7, 0x2a58 _ 0) -NAMED_CHARACTER_REFERENCE(641, /* a n */ 'd' _ 'v' _ ';', 3, 0x2a5a _ 0) -NAMED_CHARACTER_REFERENCE(642, /* a n */ 'g' _ ';', 2, 0x2220 _ 0) -NAMED_CHARACTER_REFERENCE(643, /* a n */ 'g' _ 'e' _ ';', 3, 0x29a4 _ 0) -NAMED_CHARACTER_REFERENCE(644, /* a n */ 'g' _ 'l' _ 'e' _ ';', 4, 0x2220 _ 0) -NAMED_CHARACTER_REFERENCE(645, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ ';', 5, 0x2221 _ 0) -NAMED_CHARACTER_REFERENCE(646, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'a' _ ';', 7, 0x29a8 _ 0) -NAMED_CHARACTER_REFERENCE(647, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'b' _ ';', 7, 0x29a9 _ 0) -NAMED_CHARACTER_REFERENCE(648, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'c' _ ';', 7, 0x29aa _ 0) -NAMED_CHARACTER_REFERENCE(649, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'd' _ ';', 7, 0x29ab _ 0) -NAMED_CHARACTER_REFERENCE(650, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'e' _ ';', 7, 0x29ac _ 0) -NAMED_CHARACTER_REFERENCE(651, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'f' _ ';', 7, 0x29ad _ 0) -NAMED_CHARACTER_REFERENCE(652, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'g' _ ';', 7, 0x29ae _ 0) -NAMED_CHARACTER_REFERENCE(653, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'h' _ ';', 7, 0x29af _ 0) -NAMED_CHARACTER_REFERENCE(654, /* a n */ 'g' _ 'r' _ 't' _ ';', 4, 0x221f _ 0) -NAMED_CHARACTER_REFERENCE(655, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 6, 0x22be _ 0) -NAMED_CHARACTER_REFERENCE(656, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 7, 0x299d _ 0) -NAMED_CHARACTER_REFERENCE(657, /* a n */ 'g' _ 's' _ 'p' _ 'h' _ ';', 5, 0x2222 _ 0) -NAMED_CHARACTER_REFERENCE(658, /* a n */ 'g' _ 's' _ 't' _ ';', 4, 0x00c5 _ 0) -NAMED_CHARACTER_REFERENCE(659, /* a n */ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x237c _ 0) -NAMED_CHARACTER_REFERENCE(660, /* a o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0105 _ 0) -NAMED_CHARACTER_REFERENCE(661, /* a o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd52) -NAMED_CHARACTER_REFERENCE(662, /* a p */ ';', 1, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(663, /* a p */ 'E' _ ';', 2, 0x2a70 _ 0) -NAMED_CHARACTER_REFERENCE(664, /* a p */ 'a' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2a6f _ 0) -NAMED_CHARACTER_REFERENCE(665, /* a p */ 'e' _ ';', 2, 0x224a _ 0) -NAMED_CHARACTER_REFERENCE(666, /* a p */ 'i' _ 'd' _ ';', 3, 0x224b _ 0) -NAMED_CHARACTER_REFERENCE(667, /* a p */ 'o' _ 's' _ ';', 3, 0x0027 _ 0) -NAMED_CHARACTER_REFERENCE(668, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ ';', 5, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(669, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ 'e' _ 'q' _ ';', 7, 0x224a _ 0) -NAMED_CHARACTER_REFERENCE(670, /* a r */ 'i' _ 'n' _ 'g', 3, 0x00e5 _ 0) -NAMED_CHARACTER_REFERENCE(671, /* a r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x00e5 _ 0) -NAMED_CHARACTER_REFERENCE(672, /* a s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb6) -NAMED_CHARACTER_REFERENCE(673, /* a s */ 't' _ ';', 2, 0x002a _ 0) -NAMED_CHARACTER_REFERENCE(674, /* a s */ 'y' _ 'm' _ 'p' _ ';', 4, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(675, /* a s */ 'y' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 6, 0x224d _ 0) -NAMED_CHARACTER_REFERENCE(676, /* a t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00e3 _ 0) -NAMED_CHARACTER_REFERENCE(677, /* a t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00e3 _ 0) -NAMED_CHARACTER_REFERENCE(678, /* a u */ 'm' _ 'l', 2, 0x00e4 _ 0) -NAMED_CHARACTER_REFERENCE(679, /* a u */ 'm' _ 'l' _ ';', 3, 0x00e4 _ 0) -NAMED_CHARACTER_REFERENCE(680, /* a w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2233 _ 0) -NAMED_CHARACTER_REFERENCE(681, /* a w */ 'i' _ 'n' _ 't' _ ';', 4, 0x2a11 _ 0) -NAMED_CHARACTER_REFERENCE(682, /* b N */ 'o' _ 't' _ ';', 3, 0x2aed _ 0) -NAMED_CHARACTER_REFERENCE(683, /* b a */ 'c' _ 'k' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 7, 0x224c _ 0) -NAMED_CHARACTER_REFERENCE(684, /* b a */ 'c' _ 'k' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 10, 0x03f6 _ 0) -NAMED_CHARACTER_REFERENCE(685, /* b a */ 'c' _ 'k' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 8, 0x2035 _ 0) -NAMED_CHARACTER_REFERENCE(686, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 6, 0x223d _ 0) -NAMED_CHARACTER_REFERENCE(687, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 8, 0x22cd _ 0) -NAMED_CHARACTER_REFERENCE(688, /* b a */ 'r' _ 'v' _ 'e' _ 'e' _ ';', 5, 0x22bd _ 0) -NAMED_CHARACTER_REFERENCE(689, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0x2305 _ 0) -NAMED_CHARACTER_REFERENCE(690, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0x2305 _ 0) -NAMED_CHARACTER_REFERENCE(691, /* b b */ 'r' _ 'k' _ ';', 3, 0x23b5 _ 0) -NAMED_CHARACTER_REFERENCE(692, /* b b */ 'r' _ 'k' _ 't' _ 'b' _ 'r' _ 'k' _ ';', 7, 0x23b6 _ 0) -NAMED_CHARACTER_REFERENCE(693, /* b c */ 'o' _ 'n' _ 'g' _ ';', 4, 0x224c _ 0) -NAMED_CHARACTER_REFERENCE(694, /* b c */ 'y' _ ';', 2, 0x0431 _ 0) -NAMED_CHARACTER_REFERENCE(695, /* b d */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201e _ 0) -NAMED_CHARACTER_REFERENCE(696, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ ';', 5, 0x2235 _ 0) -NAMED_CHARACTER_REFERENCE(697, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0x2235 _ 0) -NAMED_CHARACTER_REFERENCE(698, /* b e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0x29b0 _ 0) -NAMED_CHARACTER_REFERENCE(699, /* b e */ 'p' _ 's' _ 'i' _ ';', 4, 0x03f6 _ 0) -NAMED_CHARACTER_REFERENCE(700, /* b e */ 'r' _ 'n' _ 'o' _ 'u' _ ';', 5, 0x212c _ 0) -NAMED_CHARACTER_REFERENCE(701, /* b e */ 't' _ 'a' _ ';', 3, 0x03b2 _ 0) -NAMED_CHARACTER_REFERENCE(702, /* b e */ 't' _ 'h' _ ';', 3, 0x2136 _ 0) -NAMED_CHARACTER_REFERENCE(703, /* b e */ 't' _ 'w' _ 'e' _ 'e' _ 'n' _ ';', 6, 0x226c _ 0) -NAMED_CHARACTER_REFERENCE(704, /* b f */ 'r' _ ';', 2, 0xd835 _ 0xdd1f) -NAMED_CHARACTER_REFERENCE(705, /* b i */ 'g' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x22c2 _ 0) -NAMED_CHARACTER_REFERENCE(706, /* b i */ 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x25ef _ 0) -NAMED_CHARACTER_REFERENCE(707, /* b i */ 'g' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x22c3 _ 0) -NAMED_CHARACTER_REFERENCE(708, /* b i */ 'g' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2a00 _ 0) -NAMED_CHARACTER_REFERENCE(709, /* b i */ 'g' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a01 _ 0) -NAMED_CHARACTER_REFERENCE(710, /* b i */ 'g' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0x2a02 _ 0) -NAMED_CHARACTER_REFERENCE(711, /* b i */ 'g' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a06 _ 0) -NAMED_CHARACTER_REFERENCE(712, /* b i */ 'g' _ 's' _ 't' _ 'a' _ 'r' _ ';', 6, 0x2605 _ 0) -NAMED_CHARACTER_REFERENCE(713, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0x25bd _ 0) -NAMED_CHARACTER_REFERENCE(714, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'u' _ 'p' _ ';', 12, 0x25b3 _ 0) -NAMED_CHARACTER_REFERENCE(715, /* b i */ 'g' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a04 _ 0) -NAMED_CHARACTER_REFERENCE(716, /* b i */ 'g' _ 'v' _ 'e' _ 'e' _ ';', 5, 0x22c1 _ 0) -NAMED_CHARACTER_REFERENCE(717, /* b i */ 'g' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0x22c0 _ 0) -NAMED_CHARACTER_REFERENCE(718, /* b k */ 'a' _ 'r' _ 'o' _ 'w' _ ';', 5, 0x290d _ 0) -NAMED_CHARACTER_REFERENCE(719, /* b l */ 'a' _ 'c' _ 'k' _ 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 11, 0x29eb _ 0) -NAMED_CHARACTER_REFERENCE(720, /* b l */ 'a' _ 'c' _ 'k' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(721, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0x25b4 _ 0) -NAMED_CHARACTER_REFERENCE(722, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 16, 0x25be _ 0) -NAMED_CHARACTER_REFERENCE(723, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x25c2 _ 0) -NAMED_CHARACTER_REFERENCE(724, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x25b8 _ 0) -NAMED_CHARACTER_REFERENCE(725, /* b l */ 'a' _ 'n' _ 'k' _ ';', 4, 0x2423 _ 0) -NAMED_CHARACTER_REFERENCE(726, /* b l */ 'k' _ '1' _ '2' _ ';', 4, 0x2592 _ 0) -NAMED_CHARACTER_REFERENCE(727, /* b l */ 'k' _ '1' _ '4' _ ';', 4, 0x2591 _ 0) -NAMED_CHARACTER_REFERENCE(728, /* b l */ 'k' _ '3' _ '4' _ ';', 4, 0x2593 _ 0) -NAMED_CHARACTER_REFERENCE(729, /* b l */ 'o' _ 'c' _ 'k' _ ';', 4, 0x2588 _ 0) -NAMED_CHARACTER_REFERENCE(730, /* b n */ 'o' _ 't' _ ';', 3, 0x2310 _ 0) -NAMED_CHARACTER_REFERENCE(731, /* b o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd53) -NAMED_CHARACTER_REFERENCE(732, /* b o */ 't' _ ';', 2, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(733, /* b o */ 't' _ 't' _ 'o' _ 'm' _ ';', 5, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(734, /* b o */ 'w' _ 't' _ 'i' _ 'e' _ ';', 5, 0x22c8 _ 0) -NAMED_CHARACTER_REFERENCE(735, /* b o */ 'x' _ 'D' _ 'L' _ ';', 4, 0x2557 _ 0) -NAMED_CHARACTER_REFERENCE(736, /* b o */ 'x' _ 'D' _ 'R' _ ';', 4, 0x2554 _ 0) -NAMED_CHARACTER_REFERENCE(737, /* b o */ 'x' _ 'D' _ 'l' _ ';', 4, 0x2556 _ 0) -NAMED_CHARACTER_REFERENCE(738, /* b o */ 'x' _ 'D' _ 'r' _ ';', 4, 0x2553 _ 0) -NAMED_CHARACTER_REFERENCE(739, /* b o */ 'x' _ 'H' _ ';', 3, 0x2550 _ 0) -NAMED_CHARACTER_REFERENCE(740, /* b o */ 'x' _ 'H' _ 'D' _ ';', 4, 0x2566 _ 0) -NAMED_CHARACTER_REFERENCE(741, /* b o */ 'x' _ 'H' _ 'U' _ ';', 4, 0x2569 _ 0) -NAMED_CHARACTER_REFERENCE(742, /* b o */ 'x' _ 'H' _ 'd' _ ';', 4, 0x2564 _ 0) -NAMED_CHARACTER_REFERENCE(743, /* b o */ 'x' _ 'H' _ 'u' _ ';', 4, 0x2567 _ 0) -NAMED_CHARACTER_REFERENCE(744, /* b o */ 'x' _ 'U' _ 'L' _ ';', 4, 0x255d _ 0) -NAMED_CHARACTER_REFERENCE(745, /* b o */ 'x' _ 'U' _ 'R' _ ';', 4, 0x255a _ 0) -NAMED_CHARACTER_REFERENCE(746, /* b o */ 'x' _ 'U' _ 'l' _ ';', 4, 0x255c _ 0) -NAMED_CHARACTER_REFERENCE(747, /* b o */ 'x' _ 'U' _ 'r' _ ';', 4, 0x2559 _ 0) -NAMED_CHARACTER_REFERENCE(748, /* b o */ 'x' _ 'V' _ ';', 3, 0x2551 _ 0) -NAMED_CHARACTER_REFERENCE(749, /* b o */ 'x' _ 'V' _ 'H' _ ';', 4, 0x256c _ 0) -NAMED_CHARACTER_REFERENCE(750, /* b o */ 'x' _ 'V' _ 'L' _ ';', 4, 0x2563 _ 0) -NAMED_CHARACTER_REFERENCE(751, /* b o */ 'x' _ 'V' _ 'R' _ ';', 4, 0x2560 _ 0) -NAMED_CHARACTER_REFERENCE(752, /* b o */ 'x' _ 'V' _ 'h' _ ';', 4, 0x256b _ 0) -NAMED_CHARACTER_REFERENCE(753, /* b o */ 'x' _ 'V' _ 'l' _ ';', 4, 0x2562 _ 0) -NAMED_CHARACTER_REFERENCE(754, /* b o */ 'x' _ 'V' _ 'r' _ ';', 4, 0x255f _ 0) -NAMED_CHARACTER_REFERENCE(755, /* b o */ 'x' _ 'b' _ 'o' _ 'x' _ ';', 5, 0x29c9 _ 0) -NAMED_CHARACTER_REFERENCE(756, /* b o */ 'x' _ 'd' _ 'L' _ ';', 4, 0x2555 _ 0) -NAMED_CHARACTER_REFERENCE(757, /* b o */ 'x' _ 'd' _ 'R' _ ';', 4, 0x2552 _ 0) -NAMED_CHARACTER_REFERENCE(758, /* b o */ 'x' _ 'd' _ 'l' _ ';', 4, 0x2510 _ 0) -NAMED_CHARACTER_REFERENCE(759, /* b o */ 'x' _ 'd' _ 'r' _ ';', 4, 0x250c _ 0) -NAMED_CHARACTER_REFERENCE(760, /* b o */ 'x' _ 'h' _ ';', 3, 0x2500 _ 0) -NAMED_CHARACTER_REFERENCE(761, /* b o */ 'x' _ 'h' _ 'D' _ ';', 4, 0x2565 _ 0) -NAMED_CHARACTER_REFERENCE(762, /* b o */ 'x' _ 'h' _ 'U' _ ';', 4, 0x2568 _ 0) -NAMED_CHARACTER_REFERENCE(763, /* b o */ 'x' _ 'h' _ 'd' _ ';', 4, 0x252c _ 0) -NAMED_CHARACTER_REFERENCE(764, /* b o */ 'x' _ 'h' _ 'u' _ ';', 4, 0x2534 _ 0) -NAMED_CHARACTER_REFERENCE(765, /* b o */ 'x' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x229f _ 0) -NAMED_CHARACTER_REFERENCE(766, /* b o */ 'x' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x229e _ 0) -NAMED_CHARACTER_REFERENCE(767, /* b o */ 'x' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x22a0 _ 0) -NAMED_CHARACTER_REFERENCE(768, /* b o */ 'x' _ 'u' _ 'L' _ ';', 4, 0x255b _ 0) -NAMED_CHARACTER_REFERENCE(769, /* b o */ 'x' _ 'u' _ 'R' _ ';', 4, 0x2558 _ 0) -NAMED_CHARACTER_REFERENCE(770, /* b o */ 'x' _ 'u' _ 'l' _ ';', 4, 0x2518 _ 0) -NAMED_CHARACTER_REFERENCE(771, /* b o */ 'x' _ 'u' _ 'r' _ ';', 4, 0x2514 _ 0) -NAMED_CHARACTER_REFERENCE(772, /* b o */ 'x' _ 'v' _ ';', 3, 0x2502 _ 0) -NAMED_CHARACTER_REFERENCE(773, /* b o */ 'x' _ 'v' _ 'H' _ ';', 4, 0x256a _ 0) -NAMED_CHARACTER_REFERENCE(774, /* b o */ 'x' _ 'v' _ 'L' _ ';', 4, 0x2561 _ 0) -NAMED_CHARACTER_REFERENCE(775, /* b o */ 'x' _ 'v' _ 'R' _ ';', 4, 0x255e _ 0) -NAMED_CHARACTER_REFERENCE(776, /* b o */ 'x' _ 'v' _ 'h' _ ';', 4, 0x253c _ 0) -NAMED_CHARACTER_REFERENCE(777, /* b o */ 'x' _ 'v' _ 'l' _ ';', 4, 0x2524 _ 0) -NAMED_CHARACTER_REFERENCE(778, /* b o */ 'x' _ 'v' _ 'r' _ ';', 4, 0x251c _ 0) -NAMED_CHARACTER_REFERENCE(779, /* b p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2035 _ 0) -NAMED_CHARACTER_REFERENCE(780, /* b r */ 'e' _ 'v' _ 'e' _ ';', 4, 0x02d8 _ 0) -NAMED_CHARACTER_REFERENCE(781, /* b r */ 'v' _ 'b' _ 'a' _ 'r', 4, 0x00a6 _ 0) -NAMED_CHARACTER_REFERENCE(782, /* b r */ 'v' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x00a6 _ 0) -NAMED_CHARACTER_REFERENCE(783, /* b s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb7) -NAMED_CHARACTER_REFERENCE(784, /* b s */ 'e' _ 'm' _ 'i' _ ';', 4, 0x204f _ 0) -NAMED_CHARACTER_REFERENCE(785, /* b s */ 'i' _ 'm' _ ';', 3, 0x223d _ 0) -NAMED_CHARACTER_REFERENCE(786, /* b s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x22cd _ 0) -NAMED_CHARACTER_REFERENCE(787, /* b s */ 'o' _ 'l' _ ';', 3, 0x005c _ 0) -NAMED_CHARACTER_REFERENCE(788, /* b s */ 'o' _ 'l' _ 'b' _ ';', 4, 0x29c5 _ 0) -NAMED_CHARACTER_REFERENCE(789, /* b s */ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 7, 0x27c8 _ 0) -NAMED_CHARACTER_REFERENCE(790, /* b u */ 'l' _ 'l' _ ';', 3, 0x2022 _ 0) -NAMED_CHARACTER_REFERENCE(791, /* b u */ 'l' _ 'l' _ 'e' _ 't' _ ';', 5, 0x2022 _ 0) -NAMED_CHARACTER_REFERENCE(792, /* b u */ 'm' _ 'p' _ ';', 3, 0x224e _ 0) -NAMED_CHARACTER_REFERENCE(793, /* b u */ 'm' _ 'p' _ 'E' _ ';', 4, 0x2aae _ 0) -NAMED_CHARACTER_REFERENCE(794, /* b u */ 'm' _ 'p' _ 'e' _ ';', 4, 0x224f _ 0) -NAMED_CHARACTER_REFERENCE(795, /* b u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0x224f _ 0) -NAMED_CHARACTER_REFERENCE(796, /* c a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0107 _ 0) -NAMED_CHARACTER_REFERENCE(797, /* c a */ 'p' _ ';', 2, 0x2229 _ 0) -NAMED_CHARACTER_REFERENCE(798, /* c a */ 'p' _ 'a' _ 'n' _ 'd' _ ';', 5, 0x2a44 _ 0) -NAMED_CHARACTER_REFERENCE(799, /* c a */ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a49 _ 0) -NAMED_CHARACTER_REFERENCE(800, /* c a */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x2a4b _ 0) -NAMED_CHARACTER_REFERENCE(801, /* c a */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a47 _ 0) -NAMED_CHARACTER_REFERENCE(802, /* c a */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a40 _ 0) -NAMED_CHARACTER_REFERENCE(803, /* c a */ 'r' _ 'e' _ 't' _ ';', 4, 0x2041 _ 0) -NAMED_CHARACTER_REFERENCE(804, /* c a */ 'r' _ 'o' _ 'n' _ ';', 4, 0x02c7 _ 0) -NAMED_CHARACTER_REFERENCE(805, /* c c */ 'a' _ 'p' _ 's' _ ';', 4, 0x2a4d _ 0) -NAMED_CHARACTER_REFERENCE(806, /* c c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010d _ 0) -NAMED_CHARACTER_REFERENCE(807, /* c c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0x00e7 _ 0) -NAMED_CHARACTER_REFERENCE(808, /* c c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x00e7 _ 0) -NAMED_CHARACTER_REFERENCE(809, /* c c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0109 _ 0) -NAMED_CHARACTER_REFERENCE(810, /* c c */ 'u' _ 'p' _ 's' _ ';', 4, 0x2a4c _ 0) -NAMED_CHARACTER_REFERENCE(811, /* c c */ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 6, 0x2a50 _ 0) -NAMED_CHARACTER_REFERENCE(812, /* c d */ 'o' _ 't' _ ';', 3, 0x010b _ 0) -NAMED_CHARACTER_REFERENCE(813, /* c e */ 'd' _ 'i' _ 'l', 3, 0x00b8 _ 0) -NAMED_CHARACTER_REFERENCE(814, /* c e */ 'd' _ 'i' _ 'l' _ ';', 4, 0x00b8 _ 0) -NAMED_CHARACTER_REFERENCE(815, /* c e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0x29b2 _ 0) -NAMED_CHARACTER_REFERENCE(816, /* c e */ 'n' _ 't', 2, 0x00a2 _ 0) -NAMED_CHARACTER_REFERENCE(817, /* c e */ 'n' _ 't' _ ';', 3, 0x00a2 _ 0) -NAMED_CHARACTER_REFERENCE(818, /* c e */ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 8, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(819, /* c f */ 'r' _ ';', 2, 0xd835 _ 0xdd20) -NAMED_CHARACTER_REFERENCE(820, /* c h */ 'c' _ 'y' _ ';', 3, 0x0447 _ 0) -NAMED_CHARACTER_REFERENCE(821, /* c h */ 'e' _ 'c' _ 'k' _ ';', 4, 0x2713 _ 0) -NAMED_CHARACTER_REFERENCE(822, /* c h */ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 8, 0x2713 _ 0) -NAMED_CHARACTER_REFERENCE(823, /* c h */ 'i' _ ';', 2, 0x03c7 _ 0) -NAMED_CHARACTER_REFERENCE(824, /* c i */ 'r' _ ';', 2, 0x25cb _ 0) -NAMED_CHARACTER_REFERENCE(825, /* c i */ 'r' _ 'E' _ ';', 3, 0x29c3 _ 0) -NAMED_CHARACTER_REFERENCE(826, /* c i */ 'r' _ 'c' _ ';', 3, 0x02c6 _ 0) -NAMED_CHARACTER_REFERENCE(827, /* c i */ 'r' _ 'c' _ 'e' _ 'q' _ ';', 5, 0x2257 _ 0) -NAMED_CHARACTER_REFERENCE(828, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21ba _ 0) -NAMED_CHARACTER_REFERENCE(829, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21bb _ 0) -NAMED_CHARACTER_REFERENCE(830, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 7, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(831, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 7, 0x24c8 _ 0) -NAMED_CHARACTER_REFERENCE(832, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 9, 0x229b _ 0) -NAMED_CHARACTER_REFERENCE(833, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 10, 0x229a _ 0) -NAMED_CHARACTER_REFERENCE(834, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 10, 0x229d _ 0) -NAMED_CHARACTER_REFERENCE(835, /* c i */ 'r' _ 'e' _ ';', 3, 0x2257 _ 0) -NAMED_CHARACTER_REFERENCE(836, /* c i */ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a10 _ 0) -NAMED_CHARACTER_REFERENCE(837, /* c i */ 'r' _ 'm' _ 'i' _ 'd' _ ';', 5, 0x2aef _ 0) -NAMED_CHARACTER_REFERENCE(838, /* c i */ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x29c2 _ 0) -NAMED_CHARACTER_REFERENCE(839, /* c l */ 'u' _ 'b' _ 's' _ ';', 4, 0x2663 _ 0) -NAMED_CHARACTER_REFERENCE(840, /* c l */ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 7, 0x2663 _ 0) -NAMED_CHARACTER_REFERENCE(841, /* c o */ 'l' _ 'o' _ 'n' _ ';', 4, 0x003a _ 0) -NAMED_CHARACTER_REFERENCE(842, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0x2254 _ 0) -NAMED_CHARACTER_REFERENCE(843, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 6, 0x2254 _ 0) -NAMED_CHARACTER_REFERENCE(844, /* c o */ 'm' _ 'm' _ 'a' _ ';', 4, 0x002c _ 0) -NAMED_CHARACTER_REFERENCE(845, /* c o */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0x0040 _ 0) -NAMED_CHARACTER_REFERENCE(846, /* c o */ 'm' _ 'p' _ ';', 3, 0x2201 _ 0) -NAMED_CHARACTER_REFERENCE(847, /* c o */ 'm' _ 'p' _ 'f' _ 'n' _ ';', 5, 0x2218 _ 0) -NAMED_CHARACTER_REFERENCE(848, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0x2201 _ 0) -NAMED_CHARACTER_REFERENCE(849, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 8, 0x2102 _ 0) -NAMED_CHARACTER_REFERENCE(850, /* c o */ 'n' _ 'g' _ ';', 3, 0x2245 _ 0) -NAMED_CHARACTER_REFERENCE(851, /* c o */ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2a6d _ 0) -NAMED_CHARACTER_REFERENCE(852, /* c o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222e _ 0) -NAMED_CHARACTER_REFERENCE(853, /* c o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd54) -NAMED_CHARACTER_REFERENCE(854, /* c o */ 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0x2210 _ 0) -NAMED_CHARACTER_REFERENCE(855, /* c o */ 'p' _ 'y', 2, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(856, /* c o */ 'p' _ 'y' _ ';', 3, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(857, /* c o */ 'p' _ 'y' _ 's' _ 'r' _ ';', 5, 0x2117 _ 0) -NAMED_CHARACTER_REFERENCE(858, /* c r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21b5 _ 0) -NAMED_CHARACTER_REFERENCE(859, /* c r */ 'o' _ 's' _ 's' _ ';', 4, 0x2717 _ 0) -NAMED_CHARACTER_REFERENCE(860, /* c s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb8) -NAMED_CHARACTER_REFERENCE(861, /* c s */ 'u' _ 'b' _ ';', 3, 0x2acf _ 0) -NAMED_CHARACTER_REFERENCE(862, /* c s */ 'u' _ 'b' _ 'e' _ ';', 4, 0x2ad1 _ 0) -NAMED_CHARACTER_REFERENCE(863, /* c s */ 'u' _ 'p' _ ';', 3, 0x2ad0 _ 0) -NAMED_CHARACTER_REFERENCE(864, /* c s */ 'u' _ 'p' _ 'e' _ ';', 4, 0x2ad2 _ 0) -NAMED_CHARACTER_REFERENCE(865, /* c t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22ef _ 0) -NAMED_CHARACTER_REFERENCE(866, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 6, 0x2938 _ 0) -NAMED_CHARACTER_REFERENCE(867, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 6, 0x2935 _ 0) -NAMED_CHARACTER_REFERENCE(868, /* c u */ 'e' _ 'p' _ 'r' _ ';', 4, 0x22de _ 0) -NAMED_CHARACTER_REFERENCE(869, /* c u */ 'e' _ 's' _ 'c' _ ';', 4, 0x22df _ 0) -NAMED_CHARACTER_REFERENCE(870, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x21b6 _ 0) -NAMED_CHARACTER_REFERENCE(871, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 6, 0x293d _ 0) -NAMED_CHARACTER_REFERENCE(872, /* c u */ 'p' _ ';', 2, 0x222a _ 0) -NAMED_CHARACTER_REFERENCE(873, /* c u */ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 7, 0x2a48 _ 0) -NAMED_CHARACTER_REFERENCE(874, /* c u */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x2a46 _ 0) -NAMED_CHARACTER_REFERENCE(875, /* c u */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a4a _ 0) -NAMED_CHARACTER_REFERENCE(876, /* c u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0x228d _ 0) -NAMED_CHARACTER_REFERENCE(877, /* c u */ 'p' _ 'o' _ 'r' _ ';', 4, 0x2a45 _ 0) -NAMED_CHARACTER_REFERENCE(878, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x21b7 _ 0) -NAMED_CHARACTER_REFERENCE(879, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 6, 0x293c _ 0) -NAMED_CHARACTER_REFERENCE(880, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 10, 0x22de _ 0) -NAMED_CHARACTER_REFERENCE(881, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 10, 0x22df _ 0) -NAMED_CHARACTER_REFERENCE(882, /* c u */ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 7, 0x22ce _ 0) -NAMED_CHARACTER_REFERENCE(883, /* c u */ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 9, 0x22cf _ 0) -NAMED_CHARACTER_REFERENCE(884, /* c u */ 'r' _ 'r' _ 'e' _ 'n', 4, 0x00a4 _ 0) -NAMED_CHARACTER_REFERENCE(885, /* c u */ 'r' _ 'r' _ 'e' _ 'n' _ ';', 5, 0x00a4 _ 0) -NAMED_CHARACTER_REFERENCE(886, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 13, 0x21b6 _ 0) -NAMED_CHARACTER_REFERENCE(887, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 14, 0x21b7 _ 0) -NAMED_CHARACTER_REFERENCE(888, /* c u */ 'v' _ 'e' _ 'e' _ ';', 4, 0x22ce _ 0) -NAMED_CHARACTER_REFERENCE(889, /* c u */ 'w' _ 'e' _ 'd' _ ';', 4, 0x22cf _ 0) -NAMED_CHARACTER_REFERENCE(890, /* c w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2232 _ 0) -NAMED_CHARACTER_REFERENCE(891, /* c w */ 'i' _ 'n' _ 't' _ ';', 4, 0x2231 _ 0) -NAMED_CHARACTER_REFERENCE(892, /* c y */ 'l' _ 'c' _ 't' _ 'y' _ ';', 5, 0x232d _ 0) -NAMED_CHARACTER_REFERENCE(893, /* d A */ 'r' _ 'r' _ ';', 3, 0x21d3 _ 0) -NAMED_CHARACTER_REFERENCE(894, /* d H */ 'a' _ 'r' _ ';', 3, 0x2965 _ 0) -NAMED_CHARACTER_REFERENCE(895, /* d a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0x2020 _ 0) -NAMED_CHARACTER_REFERENCE(896, /* d a */ 'l' _ 'e' _ 't' _ 'h' _ ';', 5, 0x2138 _ 0) -NAMED_CHARACTER_REFERENCE(897, /* d a */ 'r' _ 'r' _ ';', 3, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(898, /* d a */ 's' _ 'h' _ ';', 3, 0x2010 _ 0) -NAMED_CHARACTER_REFERENCE(899, /* d a */ 's' _ 'h' _ 'v' _ ';', 4, 0x22a3 _ 0) -NAMED_CHARACTER_REFERENCE(900, /* d b */ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x290f _ 0) -NAMED_CHARACTER_REFERENCE(901, /* d b */ 'l' _ 'a' _ 'c' _ ';', 4, 0x02dd _ 0) -NAMED_CHARACTER_REFERENCE(902, /* d c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010f _ 0) -NAMED_CHARACTER_REFERENCE(903, /* d c */ 'y' _ ';', 2, 0x0434 _ 0) -NAMED_CHARACTER_REFERENCE(904, /* d d */ ';', 1, 0x2146 _ 0) -NAMED_CHARACTER_REFERENCE(905, /* d d */ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 6, 0x2021 _ 0) -NAMED_CHARACTER_REFERENCE(906, /* d d */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ca _ 0) -NAMED_CHARACTER_REFERENCE(907, /* d d */ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 6, 0x2a77 _ 0) -NAMED_CHARACTER_REFERENCE(908, /* d e */ 'g', 1, 0x00b0 _ 0) -NAMED_CHARACTER_REFERENCE(909, /* d e */ 'g' _ ';', 2, 0x00b0 _ 0) -NAMED_CHARACTER_REFERENCE(910, /* d e */ 'l' _ 't' _ 'a' _ ';', 4, 0x03b4 _ 0) -NAMED_CHARACTER_REFERENCE(911, /* d e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0x29b1 _ 0) -NAMED_CHARACTER_REFERENCE(912, /* d f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297f _ 0) -NAMED_CHARACTER_REFERENCE(913, /* d f */ 'r' _ ';', 2, 0xd835 _ 0xdd21) -NAMED_CHARACTER_REFERENCE(914, /* d h */ 'a' _ 'r' _ 'l' _ ';', 4, 0x21c3 _ 0) -NAMED_CHARACTER_REFERENCE(915, /* d h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c2 _ 0) -NAMED_CHARACTER_REFERENCE(916, /* d i */ 'a' _ 'm' _ ';', 3, 0x22c4 _ 0) -NAMED_CHARACTER_REFERENCE(917, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0x22c4 _ 0) -NAMED_CHARACTER_REFERENCE(918, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0x2666 _ 0) -NAMED_CHARACTER_REFERENCE(919, /* d i */ 'a' _ 'm' _ 's' _ ';', 4, 0x2666 _ 0) -NAMED_CHARACTER_REFERENCE(920, /* d i */ 'e' _ ';', 2, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(921, /* d i */ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0x03dd _ 0) -NAMED_CHARACTER_REFERENCE(922, /* d i */ 's' _ 'i' _ 'n' _ ';', 4, 0x22f2 _ 0) -NAMED_CHARACTER_REFERENCE(923, /* d i */ 'v' _ ';', 2, 0x00f7 _ 0) -NAMED_CHARACTER_REFERENCE(924, /* d i */ 'v' _ 'i' _ 'd' _ 'e', 4, 0x00f7 _ 0) -NAMED_CHARACTER_REFERENCE(925, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ ';', 5, 0x00f7 _ 0) -NAMED_CHARACTER_REFERENCE(926, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 12, 0x22c7 _ 0) -NAMED_CHARACTER_REFERENCE(927, /* d i */ 'v' _ 'o' _ 'n' _ 'x' _ ';', 5, 0x22c7 _ 0) -NAMED_CHARACTER_REFERENCE(928, /* d j */ 'c' _ 'y' _ ';', 3, 0x0452 _ 0) -NAMED_CHARACTER_REFERENCE(929, /* d l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231e _ 0) -NAMED_CHARACTER_REFERENCE(930, /* d l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230d _ 0) -NAMED_CHARACTER_REFERENCE(931, /* d o */ 'l' _ 'l' _ 'a' _ 'r' _ ';', 5, 0x0024 _ 0) -NAMED_CHARACTER_REFERENCE(932, /* d o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd55) -NAMED_CHARACTER_REFERENCE(933, /* d o */ 't' _ ';', 2, 0x02d9 _ 0) -NAMED_CHARACTER_REFERENCE(934, /* d o */ 't' _ 'e' _ 'q' _ ';', 4, 0x2250 _ 0) -NAMED_CHARACTER_REFERENCE(935, /* d o */ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2251 _ 0) -NAMED_CHARACTER_REFERENCE(936, /* d o */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2238 _ 0) -NAMED_CHARACTER_REFERENCE(937, /* d o */ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2214 _ 0) -NAMED_CHARACTER_REFERENCE(938, /* d o */ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 8, 0x22a1 _ 0) -NAMED_CHARACTER_REFERENCE(939, /* d o */ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 13, 0x2306 _ 0) -NAMED_CHARACTER_REFERENCE(940, /* d o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(941, /* d o */ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0x21ca _ 0) -NAMED_CHARACTER_REFERENCE(942, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21c3 _ 0) -NAMED_CHARACTER_REFERENCE(943, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21c2 _ 0) -NAMED_CHARACTER_REFERENCE(944, /* d r */ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0x2910 _ 0) -NAMED_CHARACTER_REFERENCE(945, /* d r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231f _ 0) -NAMED_CHARACTER_REFERENCE(946, /* d r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230c _ 0) -NAMED_CHARACTER_REFERENCE(947, /* d s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb9) -NAMED_CHARACTER_REFERENCE(948, /* d s */ 'c' _ 'y' _ ';', 3, 0x0455 _ 0) -NAMED_CHARACTER_REFERENCE(949, /* d s */ 'o' _ 'l' _ ';', 3, 0x29f6 _ 0) -NAMED_CHARACTER_REFERENCE(950, /* d s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0111 _ 0) -NAMED_CHARACTER_REFERENCE(951, /* d t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22f1 _ 0) -NAMED_CHARACTER_REFERENCE(952, /* d t */ 'r' _ 'i' _ ';', 3, 0x25bf _ 0) -NAMED_CHARACTER_REFERENCE(953, /* d t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25be _ 0) -NAMED_CHARACTER_REFERENCE(954, /* d u */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21f5 _ 0) -NAMED_CHARACTER_REFERENCE(955, /* d u */ 'h' _ 'a' _ 'r' _ ';', 4, 0x296f _ 0) -NAMED_CHARACTER_REFERENCE(956, /* d w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0x29a6 _ 0) -NAMED_CHARACTER_REFERENCE(957, /* d z */ 'c' _ 'y' _ ';', 3, 0x045f _ 0) -NAMED_CHARACTER_REFERENCE(958, /* d z */ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x27ff _ 0) -NAMED_CHARACTER_REFERENCE(959, /* e D */ 'D' _ 'o' _ 't' _ ';', 4, 0x2a77 _ 0) -NAMED_CHARACTER_REFERENCE(960, /* e D */ 'o' _ 't' _ ';', 3, 0x2251 _ 0) -NAMED_CHARACTER_REFERENCE(961, /* e a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00e9 _ 0) -NAMED_CHARACTER_REFERENCE(962, /* e a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00e9 _ 0) -NAMED_CHARACTER_REFERENCE(963, /* e a */ 's' _ 't' _ 'e' _ 'r' _ ';', 5, 0x2a6e _ 0) -NAMED_CHARACTER_REFERENCE(964, /* e c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x011b _ 0) -NAMED_CHARACTER_REFERENCE(965, /* e c */ 'i' _ 'r' _ ';', 3, 0x2256 _ 0) -NAMED_CHARACTER_REFERENCE(966, /* e c */ 'i' _ 'r' _ 'c', 3, 0x00ea _ 0) -NAMED_CHARACTER_REFERENCE(967, /* e c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ea _ 0) -NAMED_CHARACTER_REFERENCE(968, /* e c */ 'o' _ 'l' _ 'o' _ 'n' _ ';', 5, 0x2255 _ 0) -NAMED_CHARACTER_REFERENCE(969, /* e c */ 'y' _ ';', 2, 0x044d _ 0) -NAMED_CHARACTER_REFERENCE(970, /* e d */ 'o' _ 't' _ ';', 3, 0x0117 _ 0) -NAMED_CHARACTER_REFERENCE(971, /* e e */ ';', 1, 0x2147 _ 0) -NAMED_CHARACTER_REFERENCE(972, /* e f */ 'D' _ 'o' _ 't' _ ';', 4, 0x2252 _ 0) -NAMED_CHARACTER_REFERENCE(973, /* e f */ 'r' _ ';', 2, 0xd835 _ 0xdd22) -NAMED_CHARACTER_REFERENCE(974, /* e g */ ';', 1, 0x2a9a _ 0) -NAMED_CHARACTER_REFERENCE(975, /* e g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00e8 _ 0) -NAMED_CHARACTER_REFERENCE(976, /* e g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00e8 _ 0) -NAMED_CHARACTER_REFERENCE(977, /* e g */ 's' _ ';', 2, 0x2a96 _ 0) -NAMED_CHARACTER_REFERENCE(978, /* e g */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a98 _ 0) -NAMED_CHARACTER_REFERENCE(979, /* e l */ ';', 1, 0x2a99 _ 0) -NAMED_CHARACTER_REFERENCE(980, /* e l */ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 7, 0x23e7 _ 0) -NAMED_CHARACTER_REFERENCE(981, /* e l */ 'l' _ ';', 2, 0x2113 _ 0) -NAMED_CHARACTER_REFERENCE(982, /* e l */ 's' _ ';', 2, 0x2a95 _ 0) -NAMED_CHARACTER_REFERENCE(983, /* e l */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a97 _ 0) -NAMED_CHARACTER_REFERENCE(984, /* e m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0113 _ 0) -NAMED_CHARACTER_REFERENCE(985, /* e m */ 'p' _ 't' _ 'y' _ ';', 4, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(986, /* e m */ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 7, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(987, /* e m */ 'p' _ 't' _ 'y' _ 'v' _ ';', 5, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(988, /* e m */ 's' _ 'p' _ '1' _ '3' _ ';', 5, 0x2004 _ 0) -NAMED_CHARACTER_REFERENCE(989, /* e m */ 's' _ 'p' _ '1' _ '4' _ ';', 5, 0x2005 _ 0) -NAMED_CHARACTER_REFERENCE(990, /* e m */ 's' _ 'p' _ ';', 3, 0x2003 _ 0) -NAMED_CHARACTER_REFERENCE(991, /* e n */ 'g' _ ';', 2, 0x014b _ 0) -NAMED_CHARACTER_REFERENCE(992, /* e n */ 's' _ 'p' _ ';', 3, 0x2002 _ 0) -NAMED_CHARACTER_REFERENCE(993, /* e o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0119 _ 0) -NAMED_CHARACTER_REFERENCE(994, /* e o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd56) -NAMED_CHARACTER_REFERENCE(995, /* e p */ 'a' _ 'r' _ ';', 3, 0x22d5 _ 0) -NAMED_CHARACTER_REFERENCE(996, /* e p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0x29e3 _ 0) -NAMED_CHARACTER_REFERENCE(997, /* e p */ 'l' _ 'u' _ 's' _ ';', 4, 0x2a71 _ 0) -NAMED_CHARACTER_REFERENCE(998, /* e p */ 's' _ 'i' _ ';', 3, 0x03b5 _ 0) -NAMED_CHARACTER_REFERENCE(999, /* e p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x03b5 _ 0) -NAMED_CHARACTER_REFERENCE(1000, /* e p */ 's' _ 'i' _ 'v' _ ';', 4, 0x03f5 _ 0) -NAMED_CHARACTER_REFERENCE(1001, /* e q */ 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0x2256 _ 0) -NAMED_CHARACTER_REFERENCE(1002, /* e q */ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x2255 _ 0) -NAMED_CHARACTER_REFERENCE(1003, /* e q */ 's' _ 'i' _ 'm' _ ';', 4, 0x2242 _ 0) -NAMED_CHARACTER_REFERENCE(1004, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 9, 0x2a96 _ 0) -NAMED_CHARACTER_REFERENCE(1005, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0x2a95 _ 0) -NAMED_CHARACTER_REFERENCE(1006, /* e q */ 'u' _ 'a' _ 'l' _ 's' _ ';', 5, 0x003d _ 0) -NAMED_CHARACTER_REFERENCE(1007, /* e q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0x225f _ 0) -NAMED_CHARACTER_REFERENCE(1008, /* e q */ 'u' _ 'i' _ 'v' _ ';', 4, 0x2261 _ 0) -NAMED_CHARACTER_REFERENCE(1009, /* e q */ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 6, 0x2a78 _ 0) -NAMED_CHARACTER_REFERENCE(1010, /* e q */ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0x29e5 _ 0) -NAMED_CHARACTER_REFERENCE(1011, /* e r */ 'D' _ 'o' _ 't' _ ';', 4, 0x2253 _ 0) -NAMED_CHARACTER_REFERENCE(1012, /* e r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2971 _ 0) -NAMED_CHARACTER_REFERENCE(1013, /* e s */ 'c' _ 'r' _ ';', 3, 0x212f _ 0) -NAMED_CHARACTER_REFERENCE(1014, /* e s */ 'd' _ 'o' _ 't' _ ';', 4, 0x2250 _ 0) -NAMED_CHARACTER_REFERENCE(1015, /* e s */ 'i' _ 'm' _ ';', 3, 0x2242 _ 0) -NAMED_CHARACTER_REFERENCE(1016, /* e t */ 'a' _ ';', 2, 0x03b7 _ 0) -NAMED_CHARACTER_REFERENCE(1017, /* e t */ 'h', 1, 0x00f0 _ 0) -NAMED_CHARACTER_REFERENCE(1018, /* e t */ 'h' _ ';', 2, 0x00f0 _ 0) -NAMED_CHARACTER_REFERENCE(1019, /* e u */ 'm' _ 'l', 2, 0x00eb _ 0) -NAMED_CHARACTER_REFERENCE(1020, /* e u */ 'm' _ 'l' _ ';', 3, 0x00eb _ 0) -NAMED_CHARACTER_REFERENCE(1021, /* e u */ 'r' _ 'o' _ ';', 3, 0x20ac _ 0) -NAMED_CHARACTER_REFERENCE(1022, /* e x */ 'c' _ 'l' _ ';', 3, 0x0021 _ 0) -NAMED_CHARACTER_REFERENCE(1023, /* e x */ 'i' _ 's' _ 't' _ ';', 4, 0x2203 _ 0) -NAMED_CHARACTER_REFERENCE(1024, /* e x */ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 10, 0x2130 _ 0) -NAMED_CHARACTER_REFERENCE(1025, /* e x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', 11, 0x2147 _ 0) -NAMED_CHARACTER_REFERENCE(1026, /* f a */ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 12, 0x2252 _ 0) -NAMED_CHARACTER_REFERENCE(1027, /* f c */ 'y' _ ';', 2, 0x0444 _ 0) -NAMED_CHARACTER_REFERENCE(1028, /* f e */ 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0x2640 _ 0) -NAMED_CHARACTER_REFERENCE(1029, /* f f */ 'i' _ 'l' _ 'i' _ 'g' _ ';', 5, 0xfb03 _ 0) -NAMED_CHARACTER_REFERENCE(1030, /* f f */ 'l' _ 'i' _ 'g' _ ';', 4, 0xfb00 _ 0) -NAMED_CHARACTER_REFERENCE(1031, /* f f */ 'l' _ 'l' _ 'i' _ 'g' _ ';', 5, 0xfb04 _ 0) -NAMED_CHARACTER_REFERENCE(1032, /* f f */ 'r' _ ';', 2, 0xd835 _ 0xdd23) -NAMED_CHARACTER_REFERENCE(1033, /* f i */ 'l' _ 'i' _ 'g' _ ';', 4, 0xfb01 _ 0) -NAMED_CHARACTER_REFERENCE(1034, /* f l */ 'a' _ 't' _ ';', 3, 0x266d _ 0) -NAMED_CHARACTER_REFERENCE(1035, /* f l */ 'l' _ 'i' _ 'g' _ ';', 4, 0xfb02 _ 0) -NAMED_CHARACTER_REFERENCE(1036, /* f l */ 't' _ 'n' _ 's' _ ';', 4, 0x25b1 _ 0) -NAMED_CHARACTER_REFERENCE(1037, /* f n */ 'o' _ 'f' _ ';', 3, 0x0192 _ 0) -NAMED_CHARACTER_REFERENCE(1038, /* f o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd57) -NAMED_CHARACTER_REFERENCE(1039, /* f o */ 'r' _ 'a' _ 'l' _ 'l' _ ';', 5, 0x2200 _ 0) -NAMED_CHARACTER_REFERENCE(1040, /* f o */ 'r' _ 'k' _ ';', 3, 0x22d4 _ 0) -NAMED_CHARACTER_REFERENCE(1041, /* f o */ 'r' _ 'k' _ 'v' _ ';', 4, 0x2ad9 _ 0) -NAMED_CHARACTER_REFERENCE(1042, /* f p */ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a0d _ 0) -NAMED_CHARACTER_REFERENCE(1043, /* f r */ 'a' _ 'c' _ '1' _ '2', 4, 0x00bd _ 0) -NAMED_CHARACTER_REFERENCE(1044, /* f r */ 'a' _ 'c' _ '1' _ '2' _ ';', 5, 0x00bd _ 0) -NAMED_CHARACTER_REFERENCE(1045, /* f r */ 'a' _ 'c' _ '1' _ '3' _ ';', 5, 0x2153 _ 0) -NAMED_CHARACTER_REFERENCE(1046, /* f r */ 'a' _ 'c' _ '1' _ '4', 4, 0x00bc _ 0) -NAMED_CHARACTER_REFERENCE(1047, /* f r */ 'a' _ 'c' _ '1' _ '4' _ ';', 5, 0x00bc _ 0) -NAMED_CHARACTER_REFERENCE(1048, /* f r */ 'a' _ 'c' _ '1' _ '5' _ ';', 5, 0x2155 _ 0) -NAMED_CHARACTER_REFERENCE(1049, /* f r */ 'a' _ 'c' _ '1' _ '6' _ ';', 5, 0x2159 _ 0) -NAMED_CHARACTER_REFERENCE(1050, /* f r */ 'a' _ 'c' _ '1' _ '8' _ ';', 5, 0x215b _ 0) -NAMED_CHARACTER_REFERENCE(1051, /* f r */ 'a' _ 'c' _ '2' _ '3' _ ';', 5, 0x2154 _ 0) -NAMED_CHARACTER_REFERENCE(1052, /* f r */ 'a' _ 'c' _ '2' _ '5' _ ';', 5, 0x2156 _ 0) -NAMED_CHARACTER_REFERENCE(1053, /* f r */ 'a' _ 'c' _ '3' _ '4', 4, 0x00be _ 0) -NAMED_CHARACTER_REFERENCE(1054, /* f r */ 'a' _ 'c' _ '3' _ '4' _ ';', 5, 0x00be _ 0) -NAMED_CHARACTER_REFERENCE(1055, /* f r */ 'a' _ 'c' _ '3' _ '5' _ ';', 5, 0x2157 _ 0) -NAMED_CHARACTER_REFERENCE(1056, /* f r */ 'a' _ 'c' _ '3' _ '8' _ ';', 5, 0x215c _ 0) -NAMED_CHARACTER_REFERENCE(1057, /* f r */ 'a' _ 'c' _ '4' _ '5' _ ';', 5, 0x2158 _ 0) -NAMED_CHARACTER_REFERENCE(1058, /* f r */ 'a' _ 'c' _ '5' _ '6' _ ';', 5, 0x215a _ 0) -NAMED_CHARACTER_REFERENCE(1059, /* f r */ 'a' _ 'c' _ '5' _ '8' _ ';', 5, 0x215d _ 0) -NAMED_CHARACTER_REFERENCE(1060, /* f r */ 'a' _ 'c' _ '7' _ '8' _ ';', 5, 0x215e _ 0) -NAMED_CHARACTER_REFERENCE(1061, /* f r */ 'a' _ 's' _ 'l' _ ';', 4, 0x2044 _ 0) -NAMED_CHARACTER_REFERENCE(1062, /* f r */ 'o' _ 'w' _ 'n' _ ';', 4, 0x2322 _ 0) -NAMED_CHARACTER_REFERENCE(1063, /* f s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbb) -NAMED_CHARACTER_REFERENCE(1064, /* g E */ ';', 1, 0x2267 _ 0) -NAMED_CHARACTER_REFERENCE(1065, /* g E */ 'l' _ ';', 2, 0x2a8c _ 0) -NAMED_CHARACTER_REFERENCE(1066, /* g a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x01f5 _ 0) -NAMED_CHARACTER_REFERENCE(1067, /* g a */ 'm' _ 'm' _ 'a' _ ';', 4, 0x03b3 _ 0) -NAMED_CHARACTER_REFERENCE(1068, /* g a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0x03dd _ 0) -NAMED_CHARACTER_REFERENCE(1069, /* g a */ 'p' _ ';', 2, 0x2a86 _ 0) -NAMED_CHARACTER_REFERENCE(1070, /* g b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x011f _ 0) -NAMED_CHARACTER_REFERENCE(1071, /* g c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x011d _ 0) -NAMED_CHARACTER_REFERENCE(1072, /* g c */ 'y' _ ';', 2, 0x0433 _ 0) -NAMED_CHARACTER_REFERENCE(1073, /* g d */ 'o' _ 't' _ ';', 3, 0x0121 _ 0) -NAMED_CHARACTER_REFERENCE(1074, /* g e */ ';', 1, 0x2265 _ 0) -NAMED_CHARACTER_REFERENCE(1075, /* g e */ 'l' _ ';', 2, 0x22db _ 0) -NAMED_CHARACTER_REFERENCE(1076, /* g e */ 'q' _ ';', 2, 0x2265 _ 0) -NAMED_CHARACTER_REFERENCE(1077, /* g e */ 'q' _ 'q' _ ';', 3, 0x2267 _ 0) -NAMED_CHARACTER_REFERENCE(1078, /* g e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0x2a7e _ 0) -NAMED_CHARACTER_REFERENCE(1079, /* g e */ 's' _ ';', 2, 0x2a7e _ 0) -NAMED_CHARACTER_REFERENCE(1080, /* g e */ 's' _ 'c' _ 'c' _ ';', 4, 0x2aa9 _ 0) -NAMED_CHARACTER_REFERENCE(1081, /* g e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a80 _ 0) -NAMED_CHARACTER_REFERENCE(1082, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0x2a82 _ 0) -NAMED_CHARACTER_REFERENCE(1083, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 7, 0x2a84 _ 0) -NAMED_CHARACTER_REFERENCE(1084, /* g e */ 's' _ 'l' _ 'e' _ 's' _ ';', 5, 0x2a94 _ 0) -NAMED_CHARACTER_REFERENCE(1085, /* g f */ 'r' _ ';', 2, 0xd835 _ 0xdd24) -NAMED_CHARACTER_REFERENCE(1086, /* g g */ ';', 1, 0x226b _ 0) -NAMED_CHARACTER_REFERENCE(1087, /* g g */ 'g' _ ';', 2, 0x22d9 _ 0) -NAMED_CHARACTER_REFERENCE(1088, /* g i */ 'm' _ 'e' _ 'l' _ ';', 4, 0x2137 _ 0) -NAMED_CHARACTER_REFERENCE(1089, /* g j */ 'c' _ 'y' _ ';', 3, 0x0453 _ 0) -NAMED_CHARACTER_REFERENCE(1090, /* g l */ ';', 1, 0x2277 _ 0) -NAMED_CHARACTER_REFERENCE(1091, /* g l */ 'E' _ ';', 2, 0x2a92 _ 0) -NAMED_CHARACTER_REFERENCE(1092, /* g l */ 'a' _ ';', 2, 0x2aa5 _ 0) -NAMED_CHARACTER_REFERENCE(1093, /* g l */ 'j' _ ';', 2, 0x2aa4 _ 0) -NAMED_CHARACTER_REFERENCE(1094, /* g n */ 'E' _ ';', 2, 0x2269 _ 0) -NAMED_CHARACTER_REFERENCE(1095, /* g n */ 'a' _ 'p' _ ';', 3, 0x2a8a _ 0) -NAMED_CHARACTER_REFERENCE(1096, /* g n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0x2a8a _ 0) -NAMED_CHARACTER_REFERENCE(1097, /* g n */ 'e' _ ';', 2, 0x2a88 _ 0) -NAMED_CHARACTER_REFERENCE(1098, /* g n */ 'e' _ 'q' _ ';', 3, 0x2a88 _ 0) -NAMED_CHARACTER_REFERENCE(1099, /* g n */ 'e' _ 'q' _ 'q' _ ';', 4, 0x2269 _ 0) -NAMED_CHARACTER_REFERENCE(1100, /* g n */ 's' _ 'i' _ 'm' _ ';', 4, 0x22e7 _ 0) -NAMED_CHARACTER_REFERENCE(1101, /* g o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd58) -NAMED_CHARACTER_REFERENCE(1102, /* g r */ 'a' _ 'v' _ 'e' _ ';', 4, 0x0060 _ 0) -NAMED_CHARACTER_REFERENCE(1103, /* g s */ 'c' _ 'r' _ ';', 3, 0x210a _ 0) -NAMED_CHARACTER_REFERENCE(1104, /* g s */ 'i' _ 'm' _ ';', 3, 0x2273 _ 0) -NAMED_CHARACTER_REFERENCE(1105, /* g s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2a8e _ 0) -NAMED_CHARACTER_REFERENCE(1106, /* g s */ 'i' _ 'm' _ 'l' _ ';', 4, 0x2a90 _ 0) -NAMED_CHARACTER_REFERENCE(1107, /* g t */ 0, 0, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(1108, /* g t */ ';', 1, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(1109, /* g t */ 'c' _ 'c' _ ';', 3, 0x2aa7 _ 0) -NAMED_CHARACTER_REFERENCE(1110, /* g t */ 'c' _ 'i' _ 'r' _ ';', 4, 0x2a7a _ 0) -NAMED_CHARACTER_REFERENCE(1111, /* g t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22d7 _ 0) -NAMED_CHARACTER_REFERENCE(1112, /* g t */ 'l' _ 'P' _ 'a' _ 'r' _ ';', 5, 0x2995 _ 0) -NAMED_CHARACTER_REFERENCE(1113, /* g t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0x2a7c _ 0) -NAMED_CHARACTER_REFERENCE(1114, /* g t */ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0x2a86 _ 0) -NAMED_CHARACTER_REFERENCE(1115, /* g t */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2978 _ 0) -NAMED_CHARACTER_REFERENCE(1116, /* g t */ 'r' _ 'd' _ 'o' _ 't' _ ';', 5, 0x22d7 _ 0) -NAMED_CHARACTER_REFERENCE(1117, /* g t */ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0x22db _ 0) -NAMED_CHARACTER_REFERENCE(1118, /* g t */ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 9, 0x2a8c _ 0) -NAMED_CHARACTER_REFERENCE(1119, /* g t */ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0x2277 _ 0) -NAMED_CHARACTER_REFERENCE(1120, /* g t */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2273 _ 0) -NAMED_CHARACTER_REFERENCE(1121, /* h A */ 'r' _ 'r' _ ';', 3, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(1122, /* h a */ 'i' _ 'r' _ 's' _ 'p' _ ';', 5, 0x200a _ 0) -NAMED_CHARACTER_REFERENCE(1123, /* h a */ 'l' _ 'f' _ ';', 3, 0x00bd _ 0) -NAMED_CHARACTER_REFERENCE(1124, /* h a */ 'm' _ 'i' _ 'l' _ 't' _ ';', 5, 0x210b _ 0) -NAMED_CHARACTER_REFERENCE(1125, /* h a */ 'r' _ 'd' _ 'c' _ 'y' _ ';', 5, 0x044a _ 0) -NAMED_CHARACTER_REFERENCE(1126, /* h a */ 'r' _ 'r' _ ';', 3, 0x2194 _ 0) -NAMED_CHARACTER_REFERENCE(1127, /* h a */ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2948 _ 0) -NAMED_CHARACTER_REFERENCE(1128, /* h a */ 'r' _ 'r' _ 'w' _ ';', 4, 0x21ad _ 0) -NAMED_CHARACTER_REFERENCE(1129, /* h b */ 'a' _ 'r' _ ';', 3, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1130, /* h c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0125 _ 0) -NAMED_CHARACTER_REFERENCE(1131, /* h e */ 'a' _ 'r' _ 't' _ 's' _ ';', 5, 0x2665 _ 0) -NAMED_CHARACTER_REFERENCE(1132, /* h e */ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0x2665 _ 0) -NAMED_CHARACTER_REFERENCE(1133, /* h e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0x2026 _ 0) -NAMED_CHARACTER_REFERENCE(1134, /* h e */ 'r' _ 'c' _ 'o' _ 'n' _ ';', 5, 0x22b9 _ 0) -NAMED_CHARACTER_REFERENCE(1135, /* h f */ 'r' _ ';', 2, 0xd835 _ 0xdd25) -NAMED_CHARACTER_REFERENCE(1136, /* h k */ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0x2925 _ 0) -NAMED_CHARACTER_REFERENCE(1137, /* h k */ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0x2926 _ 0) -NAMED_CHARACTER_REFERENCE(1138, /* h o */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ff _ 0) -NAMED_CHARACTER_REFERENCE(1139, /* h o */ 'm' _ 't' _ 'h' _ 't' _ ';', 5, 0x223b _ 0) -NAMED_CHARACTER_REFERENCE(1140, /* h o */ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21a9 _ 0) -NAMED_CHARACTER_REFERENCE(1141, /* h o */ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x21aa _ 0) -NAMED_CHARACTER_REFERENCE(1142, /* h o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd59) -NAMED_CHARACTER_REFERENCE(1143, /* h o */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x2015 _ 0) -NAMED_CHARACTER_REFERENCE(1144, /* h s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbd) -NAMED_CHARACTER_REFERENCE(1145, /* h s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1146, /* h s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0127 _ 0) -NAMED_CHARACTER_REFERENCE(1147, /* h y */ 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0x2043 _ 0) -NAMED_CHARACTER_REFERENCE(1148, /* h y */ 'p' _ 'h' _ 'e' _ 'n' _ ';', 5, 0x2010 _ 0) -NAMED_CHARACTER_REFERENCE(1149, /* i a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00ed _ 0) -NAMED_CHARACTER_REFERENCE(1150, /* i a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00ed _ 0) -NAMED_CHARACTER_REFERENCE(1151, /* i c */ ';', 1, 0x2063 _ 0) -NAMED_CHARACTER_REFERENCE(1152, /* i c */ 'i' _ 'r' _ 'c', 3, 0x00ee _ 0) -NAMED_CHARACTER_REFERENCE(1153, /* i c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ee _ 0) -NAMED_CHARACTER_REFERENCE(1154, /* i c */ 'y' _ ';', 2, 0x0438 _ 0) -NAMED_CHARACTER_REFERENCE(1155, /* i e */ 'c' _ 'y' _ ';', 3, 0x0435 _ 0) -NAMED_CHARACTER_REFERENCE(1156, /* i e */ 'x' _ 'c' _ 'l', 3, 0x00a1 _ 0) -NAMED_CHARACTER_REFERENCE(1157, /* i e */ 'x' _ 'c' _ 'l' _ ';', 4, 0x00a1 _ 0) -NAMED_CHARACTER_REFERENCE(1158, /* i f */ 'f' _ ';', 2, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(1159, /* i f */ 'r' _ ';', 2, 0xd835 _ 0xdd26) -NAMED_CHARACTER_REFERENCE(1160, /* i g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00ec _ 0) -NAMED_CHARACTER_REFERENCE(1161, /* i g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00ec _ 0) -NAMED_CHARACTER_REFERENCE(1162, /* i i */ ';', 1, 0x2148 _ 0) -NAMED_CHARACTER_REFERENCE(1163, /* i i */ 'i' _ 'i' _ 'n' _ 't' _ ';', 5, 0x2a0c _ 0) -NAMED_CHARACTER_REFERENCE(1164, /* i i */ 'i' _ 'n' _ 't' _ ';', 4, 0x222d _ 0) -NAMED_CHARACTER_REFERENCE(1165, /* i i */ 'n' _ 'f' _ 'i' _ 'n' _ ';', 5, 0x29dc _ 0) -NAMED_CHARACTER_REFERENCE(1166, /* i i */ 'o' _ 't' _ 'a' _ ';', 4, 0x2129 _ 0) -NAMED_CHARACTER_REFERENCE(1167, /* i j */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0133 _ 0) -NAMED_CHARACTER_REFERENCE(1168, /* i m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x012b _ 0) -NAMED_CHARACTER_REFERENCE(1169, /* i m */ 'a' _ 'g' _ 'e' _ ';', 4, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(1170, /* i m */ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0x2110 _ 0) -NAMED_CHARACTER_REFERENCE(1171, /* i m */ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(1172, /* i m */ 'a' _ 't' _ 'h' _ ';', 4, 0x0131 _ 0) -NAMED_CHARACTER_REFERENCE(1173, /* i m */ 'o' _ 'f' _ ';', 3, 0x22b7 _ 0) -NAMED_CHARACTER_REFERENCE(1174, /* i m */ 'p' _ 'e' _ 'd' _ ';', 4, 0x01b5 _ 0) -NAMED_CHARACTER_REFERENCE(1175, /* i n */ ';', 1, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(1176, /* i n */ 'c' _ 'a' _ 'r' _ 'e' _ ';', 5, 0x2105 _ 0) -NAMED_CHARACTER_REFERENCE(1177, /* i n */ 'f' _ 'i' _ 'n' _ ';', 4, 0x221e _ 0) -NAMED_CHARACTER_REFERENCE(1178, /* i n */ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 7, 0x29dd _ 0) -NAMED_CHARACTER_REFERENCE(1179, /* i n */ 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0131 _ 0) -NAMED_CHARACTER_REFERENCE(1180, /* i n */ 't' _ ';', 2, 0x222b _ 0) -NAMED_CHARACTER_REFERENCE(1181, /* i n */ 't' _ 'c' _ 'a' _ 'l' _ ';', 5, 0x22ba _ 0) -NAMED_CHARACTER_REFERENCE(1182, /* i n */ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 7, 0x2124 _ 0) -NAMED_CHARACTER_REFERENCE(1183, /* i n */ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 7, 0x22ba _ 0) -NAMED_CHARACTER_REFERENCE(1184, /* i n */ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2a17 _ 0) -NAMED_CHARACTER_REFERENCE(1185, /* i n */ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0x2a3c _ 0) -NAMED_CHARACTER_REFERENCE(1186, /* i o */ 'c' _ 'y' _ ';', 3, 0x0451 _ 0) -NAMED_CHARACTER_REFERENCE(1187, /* i o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x012f _ 0) -NAMED_CHARACTER_REFERENCE(1188, /* i o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5a) -NAMED_CHARACTER_REFERENCE(1189, /* i o */ 't' _ 'a' _ ';', 3, 0x03b9 _ 0) -NAMED_CHARACTER_REFERENCE(1190, /* i p */ 'r' _ 'o' _ 'd' _ ';', 4, 0x2a3c _ 0) -NAMED_CHARACTER_REFERENCE(1191, /* i q */ 'u' _ 'e' _ 's' _ 't', 4, 0x00bf _ 0) -NAMED_CHARACTER_REFERENCE(1192, /* i q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0x00bf _ 0) -NAMED_CHARACTER_REFERENCE(1193, /* i s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbe) -NAMED_CHARACTER_REFERENCE(1194, /* i s */ 'i' _ 'n' _ ';', 3, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(1195, /* i s */ 'i' _ 'n' _ 'E' _ ';', 4, 0x22f9 _ 0) -NAMED_CHARACTER_REFERENCE(1196, /* i s */ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22f5 _ 0) -NAMED_CHARACTER_REFERENCE(1197, /* i s */ 'i' _ 'n' _ 's' _ ';', 4, 0x22f4 _ 0) -NAMED_CHARACTER_REFERENCE(1198, /* i s */ 'i' _ 'n' _ 's' _ 'v' _ ';', 5, 0x22f3 _ 0) -NAMED_CHARACTER_REFERENCE(1199, /* i s */ 'i' _ 'n' _ 'v' _ ';', 4, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(1200, /* i t */ ';', 1, 0x2062 _ 0) -NAMED_CHARACTER_REFERENCE(1201, /* i t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0129 _ 0) -NAMED_CHARACTER_REFERENCE(1202, /* i u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0456 _ 0) -NAMED_CHARACTER_REFERENCE(1203, /* i u */ 'm' _ 'l', 2, 0x00ef _ 0) -NAMED_CHARACTER_REFERENCE(1204, /* i u */ 'm' _ 'l' _ ';', 3, 0x00ef _ 0) -NAMED_CHARACTER_REFERENCE(1205, /* j c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0135 _ 0) -NAMED_CHARACTER_REFERENCE(1206, /* j c */ 'y' _ ';', 2, 0x0439 _ 0) -NAMED_CHARACTER_REFERENCE(1207, /* j f */ 'r' _ ';', 2, 0xd835 _ 0xdd27) -NAMED_CHARACTER_REFERENCE(1208, /* j m */ 'a' _ 't' _ 'h' _ ';', 4, 0x0237 _ 0) -NAMED_CHARACTER_REFERENCE(1209, /* j o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5b) -NAMED_CHARACTER_REFERENCE(1210, /* j s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbf) -NAMED_CHARACTER_REFERENCE(1211, /* j s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0x0458 _ 0) -NAMED_CHARACTER_REFERENCE(1212, /* j u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0454 _ 0) -NAMED_CHARACTER_REFERENCE(1213, /* k a */ 'p' _ 'p' _ 'a' _ ';', 4, 0x03ba _ 0) -NAMED_CHARACTER_REFERENCE(1214, /* k a */ 'p' _ 'p' _ 'a' _ 'v' _ ';', 5, 0x03f0 _ 0) -NAMED_CHARACTER_REFERENCE(1215, /* k c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0137 _ 0) -NAMED_CHARACTER_REFERENCE(1216, /* k c */ 'y' _ ';', 2, 0x043a _ 0) -NAMED_CHARACTER_REFERENCE(1217, /* k f */ 'r' _ ';', 2, 0xd835 _ 0xdd28) -NAMED_CHARACTER_REFERENCE(1218, /* k g */ 'r' _ 'e' _ 'e' _ 'n' _ ';', 5, 0x0138 _ 0) -NAMED_CHARACTER_REFERENCE(1219, /* k h */ 'c' _ 'y' _ ';', 3, 0x0445 _ 0) -NAMED_CHARACTER_REFERENCE(1220, /* k j */ 'c' _ 'y' _ ';', 3, 0x045c _ 0) -NAMED_CHARACTER_REFERENCE(1221, /* k o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5c) -NAMED_CHARACTER_REFERENCE(1222, /* k s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc0) -NAMED_CHARACTER_REFERENCE(1223, /* l A */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21da _ 0) -NAMED_CHARACTER_REFERENCE(1224, /* l A */ 'r' _ 'r' _ ';', 3, 0x21d0 _ 0) -NAMED_CHARACTER_REFERENCE(1225, /* l A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x291b _ 0) -NAMED_CHARACTER_REFERENCE(1226, /* l B */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290e _ 0) -NAMED_CHARACTER_REFERENCE(1227, /* l E */ ';', 1, 0x2266 _ 0) -NAMED_CHARACTER_REFERENCE(1228, /* l E */ 'g' _ ';', 2, 0x2a8b _ 0) -NAMED_CHARACTER_REFERENCE(1229, /* l H */ 'a' _ 'r' _ ';', 3, 0x2962 _ 0) -NAMED_CHARACTER_REFERENCE(1230, /* l a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x013a _ 0) -NAMED_CHARACTER_REFERENCE(1231, /* l a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0x29b4 _ 0) -NAMED_CHARACTER_REFERENCE(1232, /* l a */ 'g' _ 'r' _ 'a' _ 'n' _ ';', 5, 0x2112 _ 0) -NAMED_CHARACTER_REFERENCE(1233, /* l a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0x03bb _ 0) -NAMED_CHARACTER_REFERENCE(1234, /* l a */ 'n' _ 'g' _ ';', 3, 0x27e8 _ 0) -NAMED_CHARACTER_REFERENCE(1235, /* l a */ 'n' _ 'g' _ 'd' _ ';', 4, 0x2991 _ 0) -NAMED_CHARACTER_REFERENCE(1236, /* l a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0x27e8 _ 0) -NAMED_CHARACTER_REFERENCE(1237, /* l a */ 'p' _ ';', 2, 0x2a85 _ 0) -NAMED_CHARACTER_REFERENCE(1238, /* l a */ 'q' _ 'u' _ 'o', 3, 0x00ab _ 0) -NAMED_CHARACTER_REFERENCE(1239, /* l a */ 'q' _ 'u' _ 'o' _ ';', 4, 0x00ab _ 0) -NAMED_CHARACTER_REFERENCE(1240, /* l a */ 'r' _ 'r' _ ';', 3, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(1241, /* l a */ 'r' _ 'r' _ 'b' _ ';', 4, 0x21e4 _ 0) -NAMED_CHARACTER_REFERENCE(1242, /* l a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0x291f _ 0) -NAMED_CHARACTER_REFERENCE(1243, /* l a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0x291d _ 0) -NAMED_CHARACTER_REFERENCE(1244, /* l a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x21a9 _ 0) -NAMED_CHARACTER_REFERENCE(1245, /* l a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0x21ab _ 0) -NAMED_CHARACTER_REFERENCE(1246, /* l a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0x2939 _ 0) -NAMED_CHARACTER_REFERENCE(1247, /* l a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2973 _ 0) -NAMED_CHARACTER_REFERENCE(1248, /* l a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0x21a2 _ 0) -NAMED_CHARACTER_REFERENCE(1249, /* l a */ 't' _ ';', 2, 0x2aab _ 0) -NAMED_CHARACTER_REFERENCE(1250, /* l a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x2919 _ 0) -NAMED_CHARACTER_REFERENCE(1251, /* l a */ 't' _ 'e' _ ';', 3, 0x2aad _ 0) -NAMED_CHARACTER_REFERENCE(1252, /* l b */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290c _ 0) -NAMED_CHARACTER_REFERENCE(1253, /* l b */ 'b' _ 'r' _ 'k' _ ';', 4, 0x2772 _ 0) -NAMED_CHARACTER_REFERENCE(1254, /* l b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0x007b _ 0) -NAMED_CHARACTER_REFERENCE(1255, /* l b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0x005b _ 0) -NAMED_CHARACTER_REFERENCE(1256, /* l b */ 'r' _ 'k' _ 'e' _ ';', 4, 0x298b _ 0) -NAMED_CHARACTER_REFERENCE(1257, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0x298f _ 0) -NAMED_CHARACTER_REFERENCE(1258, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0x298d _ 0) -NAMED_CHARACTER_REFERENCE(1259, /* l c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x013e _ 0) -NAMED_CHARACTER_REFERENCE(1260, /* l c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x013c _ 0) -NAMED_CHARACTER_REFERENCE(1261, /* l c */ 'e' _ 'i' _ 'l' _ ';', 4, 0x2308 _ 0) -NAMED_CHARACTER_REFERENCE(1262, /* l c */ 'u' _ 'b' _ ';', 3, 0x007b _ 0) -NAMED_CHARACTER_REFERENCE(1263, /* l c */ 'y' _ ';', 2, 0x043b _ 0) -NAMED_CHARACTER_REFERENCE(1264, /* l d */ 'c' _ 'a' _ ';', 3, 0x2936 _ 0) -NAMED_CHARACTER_REFERENCE(1265, /* l d */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201c _ 0) -NAMED_CHARACTER_REFERENCE(1266, /* l d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x201e _ 0) -NAMED_CHARACTER_REFERENCE(1267, /* l d */ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2967 _ 0) -NAMED_CHARACTER_REFERENCE(1268, /* l d */ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0x294b _ 0) -NAMED_CHARACTER_REFERENCE(1269, /* l d */ 's' _ 'h' _ ';', 3, 0x21b2 _ 0) -NAMED_CHARACTER_REFERENCE(1270, /* l e */ ';', 1, 0x2264 _ 0) -NAMED_CHARACTER_REFERENCE(1271, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(1272, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 12, 0x21a2 _ 0) -NAMED_CHARACTER_REFERENCE(1273, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0x21bd _ 0) -NAMED_CHARACTER_REFERENCE(1274, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 12, 0x21bc _ 0) -NAMED_CHARACTER_REFERENCE(1275, /* l e */ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0x21c7 _ 0) -NAMED_CHARACTER_REFERENCE(1276, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2194 _ 0) -NAMED_CHARACTER_REFERENCE(1277, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0x21c6 _ 0) -NAMED_CHARACTER_REFERENCE(1278, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0x21cb _ 0) -NAMED_CHARACTER_REFERENCE(1279, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21ad _ 0) -NAMED_CHARACTER_REFERENCE(1280, /* l e */ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0x22cb _ 0) -NAMED_CHARACTER_REFERENCE(1281, /* l e */ 'g' _ ';', 2, 0x22da _ 0) -NAMED_CHARACTER_REFERENCE(1282, /* l e */ 'q' _ ';', 2, 0x2264 _ 0) -NAMED_CHARACTER_REFERENCE(1283, /* l e */ 'q' _ 'q' _ ';', 3, 0x2266 _ 0) -NAMED_CHARACTER_REFERENCE(1284, /* l e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0x2a7d _ 0) -NAMED_CHARACTER_REFERENCE(1285, /* l e */ 's' _ ';', 2, 0x2a7d _ 0) -NAMED_CHARACTER_REFERENCE(1286, /* l e */ 's' _ 'c' _ 'c' _ ';', 4, 0x2aa8 _ 0) -NAMED_CHARACTER_REFERENCE(1287, /* l e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a7f _ 0) -NAMED_CHARACTER_REFERENCE(1288, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0x2a81 _ 0) -NAMED_CHARACTER_REFERENCE(1289, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 7, 0x2a83 _ 0) -NAMED_CHARACTER_REFERENCE(1290, /* l e */ 's' _ 'g' _ 'e' _ 's' _ ';', 5, 0x2a93 _ 0) -NAMED_CHARACTER_REFERENCE(1291, /* l e */ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2a85 _ 0) -NAMED_CHARACTER_REFERENCE(1292, /* l e */ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22d6 _ 0) -NAMED_CHARACTER_REFERENCE(1293, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 8, 0x22da _ 0) -NAMED_CHARACTER_REFERENCE(1294, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 9, 0x2a8b _ 0) -NAMED_CHARACTER_REFERENCE(1295, /* l e */ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 6, 0x2276 _ 0) -NAMED_CHARACTER_REFERENCE(1296, /* l e */ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2272 _ 0) -NAMED_CHARACTER_REFERENCE(1297, /* l f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297c _ 0) -NAMED_CHARACTER_REFERENCE(1298, /* l f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0x230a _ 0) -NAMED_CHARACTER_REFERENCE(1299, /* l f */ 'r' _ ';', 2, 0xd835 _ 0xdd29) -NAMED_CHARACTER_REFERENCE(1300, /* l g */ ';', 1, 0x2276 _ 0) -NAMED_CHARACTER_REFERENCE(1301, /* l g */ 'E' _ ';', 2, 0x2a91 _ 0) -NAMED_CHARACTER_REFERENCE(1302, /* l h */ 'a' _ 'r' _ 'd' _ ';', 4, 0x21bd _ 0) -NAMED_CHARACTER_REFERENCE(1303, /* l h */ 'a' _ 'r' _ 'u' _ ';', 4, 0x21bc _ 0) -NAMED_CHARACTER_REFERENCE(1304, /* l h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0x296a _ 0) -NAMED_CHARACTER_REFERENCE(1305, /* l h */ 'b' _ 'l' _ 'k' _ ';', 4, 0x2584 _ 0) -NAMED_CHARACTER_REFERENCE(1306, /* l j */ 'c' _ 'y' _ ';', 3, 0x0459 _ 0) -NAMED_CHARACTER_REFERENCE(1307, /* l l */ ';', 1, 0x226a _ 0) -NAMED_CHARACTER_REFERENCE(1308, /* l l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c7 _ 0) -NAMED_CHARACTER_REFERENCE(1309, /* l l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231e _ 0) -NAMED_CHARACTER_REFERENCE(1310, /* l l */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0x296b _ 0) -NAMED_CHARACTER_REFERENCE(1311, /* l l */ 't' _ 'r' _ 'i' _ ';', 4, 0x25fa _ 0) -NAMED_CHARACTER_REFERENCE(1312, /* l m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0140 _ 0) -NAMED_CHARACTER_REFERENCE(1313, /* l m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0x23b0 _ 0) -NAMED_CHARACTER_REFERENCE(1314, /* l m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0x23b0 _ 0) -NAMED_CHARACTER_REFERENCE(1315, /* l n */ 'E' _ ';', 2, 0x2268 _ 0) -NAMED_CHARACTER_REFERENCE(1316, /* l n */ 'a' _ 'p' _ ';', 3, 0x2a89 _ 0) -NAMED_CHARACTER_REFERENCE(1317, /* l n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0x2a89 _ 0) -NAMED_CHARACTER_REFERENCE(1318, /* l n */ 'e' _ ';', 2, 0x2a87 _ 0) -NAMED_CHARACTER_REFERENCE(1319, /* l n */ 'e' _ 'q' _ ';', 3, 0x2a87 _ 0) -NAMED_CHARACTER_REFERENCE(1320, /* l n */ 'e' _ 'q' _ 'q' _ ';', 4, 0x2268 _ 0) -NAMED_CHARACTER_REFERENCE(1321, /* l n */ 's' _ 'i' _ 'm' _ ';', 4, 0x22e6 _ 0) -NAMED_CHARACTER_REFERENCE(1322, /* l o */ 'a' _ 'n' _ 'g' _ ';', 4, 0x27ec _ 0) -NAMED_CHARACTER_REFERENCE(1323, /* l o */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21fd _ 0) -NAMED_CHARACTER_REFERENCE(1324, /* l o */ 'b' _ 'r' _ 'k' _ ';', 4, 0x27e6 _ 0) -NAMED_CHARACTER_REFERENCE(1325, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x27f5 _ 0) -NAMED_CHARACTER_REFERENCE(1326, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x27f7 _ 0) -NAMED_CHARACTER_REFERENCE(1327, /* l o */ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 9, 0x27fc _ 0) -NAMED_CHARACTER_REFERENCE(1328, /* l o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x27f6 _ 0) -NAMED_CHARACTER_REFERENCE(1329, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0x21ab _ 0) -NAMED_CHARACTER_REFERENCE(1330, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0x21ac _ 0) -NAMED_CHARACTER_REFERENCE(1331, /* l o */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2985 _ 0) -NAMED_CHARACTER_REFERENCE(1332, /* l o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5d) -NAMED_CHARACTER_REFERENCE(1333, /* l o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a2d _ 0) -NAMED_CHARACTER_REFERENCE(1334, /* l o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0x2a34 _ 0) -NAMED_CHARACTER_REFERENCE(1335, /* l o */ 'w' _ 'a' _ 's' _ 't' _ ';', 5, 0x2217 _ 0) -NAMED_CHARACTER_REFERENCE(1336, /* l o */ 'w' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x005f _ 0) -NAMED_CHARACTER_REFERENCE(1337, /* l o */ 'z' _ ';', 2, 0x25ca _ 0) -NAMED_CHARACTER_REFERENCE(1338, /* l o */ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 6, 0x25ca _ 0) -NAMED_CHARACTER_REFERENCE(1339, /* l o */ 'z' _ 'f' _ ';', 3, 0x29eb _ 0) -NAMED_CHARACTER_REFERENCE(1340, /* l p */ 'a' _ 'r' _ ';', 3, 0x0028 _ 0) -NAMED_CHARACTER_REFERENCE(1341, /* l p */ 'a' _ 'r' _ 'l' _ 't' _ ';', 5, 0x2993 _ 0) -NAMED_CHARACTER_REFERENCE(1342, /* l r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c6 _ 0) -NAMED_CHARACTER_REFERENCE(1343, /* l r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231f _ 0) -NAMED_CHARACTER_REFERENCE(1344, /* l r */ 'h' _ 'a' _ 'r' _ ';', 4, 0x21cb _ 0) -NAMED_CHARACTER_REFERENCE(1345, /* l r */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0x296d _ 0) -NAMED_CHARACTER_REFERENCE(1346, /* l r */ 'm' _ ';', 2, 0x200e _ 0) -NAMED_CHARACTER_REFERENCE(1347, /* l r */ 't' _ 'r' _ 'i' _ ';', 4, 0x22bf _ 0) -NAMED_CHARACTER_REFERENCE(1348, /* l s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0x2039 _ 0) -NAMED_CHARACTER_REFERENCE(1349, /* l s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc1) -NAMED_CHARACTER_REFERENCE(1350, /* l s */ 'h' _ ';', 2, 0x21b0 _ 0) -NAMED_CHARACTER_REFERENCE(1351, /* l s */ 'i' _ 'm' _ ';', 3, 0x2272 _ 0) -NAMED_CHARACTER_REFERENCE(1352, /* l s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2a8d _ 0) -NAMED_CHARACTER_REFERENCE(1353, /* l s */ 'i' _ 'm' _ 'g' _ ';', 4, 0x2a8f _ 0) -NAMED_CHARACTER_REFERENCE(1354, /* l s */ 'q' _ 'b' _ ';', 3, 0x005b _ 0) -NAMED_CHARACTER_REFERENCE(1355, /* l s */ 'q' _ 'u' _ 'o' _ ';', 4, 0x2018 _ 0) -NAMED_CHARACTER_REFERENCE(1356, /* l s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x201a _ 0) -NAMED_CHARACTER_REFERENCE(1357, /* l s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0142 _ 0) -NAMED_CHARACTER_REFERENCE(1358, /* l t */ 0, 0, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(1359, /* l t */ ';', 1, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(1360, /* l t */ 'c' _ 'c' _ ';', 3, 0x2aa6 _ 0) -NAMED_CHARACTER_REFERENCE(1361, /* l t */ 'c' _ 'i' _ 'r' _ ';', 4, 0x2a79 _ 0) -NAMED_CHARACTER_REFERENCE(1362, /* l t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22d6 _ 0) -NAMED_CHARACTER_REFERENCE(1363, /* l t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0x22cb _ 0) -NAMED_CHARACTER_REFERENCE(1364, /* l t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x22c9 _ 0) -NAMED_CHARACTER_REFERENCE(1365, /* l t */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2976 _ 0) -NAMED_CHARACTER_REFERENCE(1366, /* l t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0x2a7b _ 0) -NAMED_CHARACTER_REFERENCE(1367, /* l t */ 'r' _ 'P' _ 'a' _ 'r' _ ';', 5, 0x2996 _ 0) -NAMED_CHARACTER_REFERENCE(1368, /* l t */ 'r' _ 'i' _ ';', 3, 0x25c3 _ 0) -NAMED_CHARACTER_REFERENCE(1369, /* l t */ 'r' _ 'i' _ 'e' _ ';', 4, 0x22b4 _ 0) -NAMED_CHARACTER_REFERENCE(1370, /* l t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25c2 _ 0) -NAMED_CHARACTER_REFERENCE(1371, /* l u */ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0x294a _ 0) -NAMED_CHARACTER_REFERENCE(1372, /* l u */ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2966 _ 0) -NAMED_CHARACTER_REFERENCE(1373, /* m D */ 'D' _ 'o' _ 't' _ ';', 4, 0x223a _ 0) -NAMED_CHARACTER_REFERENCE(1374, /* m a */ 'c' _ 'r', 2, 0x00af _ 0) -NAMED_CHARACTER_REFERENCE(1375, /* m a */ 'c' _ 'r' _ ';', 3, 0x00af _ 0) -NAMED_CHARACTER_REFERENCE(1376, /* m a */ 'l' _ 'e' _ ';', 3, 0x2642 _ 0) -NAMED_CHARACTER_REFERENCE(1377, /* m a */ 'l' _ 't' _ ';', 3, 0x2720 _ 0) -NAMED_CHARACTER_REFERENCE(1378, /* m a */ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 6, 0x2720 _ 0) -NAMED_CHARACTER_REFERENCE(1379, /* m a */ 'p' _ ';', 2, 0x21a6 _ 0) -NAMED_CHARACTER_REFERENCE(1380, /* m a */ 'p' _ 's' _ 't' _ 'o' _ ';', 5, 0x21a6 _ 0) -NAMED_CHARACTER_REFERENCE(1381, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 9, 0x21a7 _ 0) -NAMED_CHARACTER_REFERENCE(1382, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 9, 0x21a4 _ 0) -NAMED_CHARACTER_REFERENCE(1383, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 7, 0x21a5 _ 0) -NAMED_CHARACTER_REFERENCE(1384, /* m a */ 'r' _ 'k' _ 'e' _ 'r' _ ';', 5, 0x25ae _ 0) -NAMED_CHARACTER_REFERENCE(1385, /* m c */ 'o' _ 'm' _ 'm' _ 'a' _ ';', 5, 0x2a29 _ 0) -NAMED_CHARACTER_REFERENCE(1386, /* m c */ 'y' _ ';', 2, 0x043c _ 0) -NAMED_CHARACTER_REFERENCE(1387, /* m d */ 'a' _ 's' _ 'h' _ ';', 4, 0x2014 _ 0) -NAMED_CHARACTER_REFERENCE(1388, /* m e */ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0x2221 _ 0) -NAMED_CHARACTER_REFERENCE(1389, /* m f */ 'r' _ ';', 2, 0xd835 _ 0xdd2a) -NAMED_CHARACTER_REFERENCE(1390, /* m h */ 'o' _ ';', 2, 0x2127 _ 0) -NAMED_CHARACTER_REFERENCE(1391, /* m i */ 'c' _ 'r' _ 'o', 3, 0x00b5 _ 0) -NAMED_CHARACTER_REFERENCE(1392, /* m i */ 'c' _ 'r' _ 'o' _ ';', 4, 0x00b5 _ 0) -NAMED_CHARACTER_REFERENCE(1393, /* m i */ 'd' _ ';', 2, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(1394, /* m i */ 'd' _ 'a' _ 's' _ 't' _ ';', 5, 0x002a _ 0) -NAMED_CHARACTER_REFERENCE(1395, /* m i */ 'd' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2af0 _ 0) -NAMED_CHARACTER_REFERENCE(1396, /* m i */ 'd' _ 'd' _ 'o' _ 't', 4, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(1397, /* m i */ 'd' _ 'd' _ 'o' _ 't' _ ';', 5, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(1398, /* m i */ 'n' _ 'u' _ 's' _ ';', 4, 0x2212 _ 0) -NAMED_CHARACTER_REFERENCE(1399, /* m i */ 'n' _ 'u' _ 's' _ 'b' _ ';', 5, 0x229f _ 0) -NAMED_CHARACTER_REFERENCE(1400, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ ';', 5, 0x2238 _ 0) -NAMED_CHARACTER_REFERENCE(1401, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 6, 0x2a2a _ 0) -NAMED_CHARACTER_REFERENCE(1402, /* m l */ 'c' _ 'p' _ ';', 3, 0x2adb _ 0) -NAMED_CHARACTER_REFERENCE(1403, /* m l */ 'd' _ 'r' _ ';', 3, 0x2026 _ 0) -NAMED_CHARACTER_REFERENCE(1404, /* m n */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2213 _ 0) -NAMED_CHARACTER_REFERENCE(1405, /* m o */ 'd' _ 'e' _ 'l' _ 's' _ ';', 5, 0x22a7 _ 0) -NAMED_CHARACTER_REFERENCE(1406, /* m o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5e) -NAMED_CHARACTER_REFERENCE(1407, /* m p */ ';', 1, 0x2213 _ 0) -NAMED_CHARACTER_REFERENCE(1408, /* m s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc2) -NAMED_CHARACTER_REFERENCE(1409, /* m s */ 't' _ 'p' _ 'o' _ 's' _ ';', 5, 0x223e _ 0) -NAMED_CHARACTER_REFERENCE(1410, /* m u */ ';', 1, 0x03bc _ 0) -NAMED_CHARACTER_REFERENCE(1411, /* m u */ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 7, 0x22b8 _ 0) -NAMED_CHARACTER_REFERENCE(1412, /* m u */ 'm' _ 'a' _ 'p' _ ';', 4, 0x22b8 _ 0) -NAMED_CHARACTER_REFERENCE(1413, /* n L */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21cd _ 0) -NAMED_CHARACTER_REFERENCE(1414, /* n L */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21ce _ 0) -NAMED_CHARACTER_REFERENCE(1415, /* n R */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x21cf _ 0) -NAMED_CHARACTER_REFERENCE(1416, /* n V */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22af _ 0) -NAMED_CHARACTER_REFERENCE(1417, /* n V */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22ae _ 0) -NAMED_CHARACTER_REFERENCE(1418, /* n a */ 'b' _ 'l' _ 'a' _ ';', 4, 0x2207 _ 0) -NAMED_CHARACTER_REFERENCE(1419, /* n a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0144 _ 0) -NAMED_CHARACTER_REFERENCE(1420, /* n a */ 'p' _ ';', 2, 0x2249 _ 0) -NAMED_CHARACTER_REFERENCE(1421, /* n a */ 'p' _ 'o' _ 's' _ ';', 4, 0x0149 _ 0) -NAMED_CHARACTER_REFERENCE(1422, /* n a */ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 6, 0x2249 _ 0) -NAMED_CHARACTER_REFERENCE(1423, /* n a */ 't' _ 'u' _ 'r' _ ';', 4, 0x266e _ 0) -NAMED_CHARACTER_REFERENCE(1424, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 6, 0x266e _ 0) -NAMED_CHARACTER_REFERENCE(1425, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 7, 0x2115 _ 0) -NAMED_CHARACTER_REFERENCE(1426, /* n b */ 's' _ 'p', 2, 0x00a0 _ 0) -NAMED_CHARACTER_REFERENCE(1427, /* n b */ 's' _ 'p' _ ';', 3, 0x00a0 _ 0) -NAMED_CHARACTER_REFERENCE(1428, /* n c */ 'a' _ 'p' _ ';', 3, 0x2a43 _ 0) -NAMED_CHARACTER_REFERENCE(1429, /* n c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0148 _ 0) -NAMED_CHARACTER_REFERENCE(1430, /* n c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0146 _ 0) -NAMED_CHARACTER_REFERENCE(1431, /* n c */ 'o' _ 'n' _ 'g' _ ';', 4, 0x2247 _ 0) -NAMED_CHARACTER_REFERENCE(1432, /* n c */ 'u' _ 'p' _ ';', 3, 0x2a42 _ 0) -NAMED_CHARACTER_REFERENCE(1433, /* n c */ 'y' _ ';', 2, 0x043d _ 0) -NAMED_CHARACTER_REFERENCE(1434, /* n d */ 'a' _ 's' _ 'h' _ ';', 4, 0x2013 _ 0) -NAMED_CHARACTER_REFERENCE(1435, /* n e */ ';', 1, 0x2260 _ 0) -NAMED_CHARACTER_REFERENCE(1436, /* n e */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d7 _ 0) -NAMED_CHARACTER_REFERENCE(1437, /* n e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2924 _ 0) -NAMED_CHARACTER_REFERENCE(1438, /* n e */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2197 _ 0) -NAMED_CHARACTER_REFERENCE(1439, /* n e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2197 _ 0) -NAMED_CHARACTER_REFERENCE(1440, /* n e */ 'q' _ 'u' _ 'i' _ 'v' _ ';', 5, 0x2262 _ 0) -NAMED_CHARACTER_REFERENCE(1441, /* n e */ 's' _ 'e' _ 'a' _ 'r' _ ';', 5, 0x2928 _ 0) -NAMED_CHARACTER_REFERENCE(1442, /* n e */ 'x' _ 'i' _ 's' _ 't' _ ';', 5, 0x2204 _ 0) -NAMED_CHARACTER_REFERENCE(1443, /* n e */ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 6, 0x2204 _ 0) -NAMED_CHARACTER_REFERENCE(1444, /* n f */ 'r' _ ';', 2, 0xd835 _ 0xdd2b) -NAMED_CHARACTER_REFERENCE(1445, /* n g */ 'e' _ ';', 2, 0x2271 _ 0) -NAMED_CHARACTER_REFERENCE(1446, /* n g */ 'e' _ 'q' _ ';', 3, 0x2271 _ 0) -NAMED_CHARACTER_REFERENCE(1447, /* n g */ 's' _ 'i' _ 'm' _ ';', 4, 0x2275 _ 0) -NAMED_CHARACTER_REFERENCE(1448, /* n g */ 't' _ ';', 2, 0x226f _ 0) -NAMED_CHARACTER_REFERENCE(1449, /* n g */ 't' _ 'r' _ ';', 3, 0x226f _ 0) -NAMED_CHARACTER_REFERENCE(1450, /* n h */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21ce _ 0) -NAMED_CHARACTER_REFERENCE(1451, /* n h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ae _ 0) -NAMED_CHARACTER_REFERENCE(1452, /* n h */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2af2 _ 0) -NAMED_CHARACTER_REFERENCE(1453, /* n i */ ';', 1, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(1454, /* n i */ 's' _ ';', 2, 0x22fc _ 0) -NAMED_CHARACTER_REFERENCE(1455, /* n i */ 's' _ 'd' _ ';', 3, 0x22fa _ 0) -NAMED_CHARACTER_REFERENCE(1456, /* n i */ 'v' _ ';', 2, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(1457, /* n j */ 'c' _ 'y' _ ';', 3, 0x045a _ 0) -NAMED_CHARACTER_REFERENCE(1458, /* n l */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21cd _ 0) -NAMED_CHARACTER_REFERENCE(1459, /* n l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x219a _ 0) -NAMED_CHARACTER_REFERENCE(1460, /* n l */ 'd' _ 'r' _ ';', 3, 0x2025 _ 0) -NAMED_CHARACTER_REFERENCE(1461, /* n l */ 'e' _ ';', 2, 0x2270 _ 0) -NAMED_CHARACTER_REFERENCE(1462, /* n l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x219a _ 0) -NAMED_CHARACTER_REFERENCE(1463, /* n l */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21ae _ 0) -NAMED_CHARACTER_REFERENCE(1464, /* n l */ 'e' _ 'q' _ ';', 3, 0x2270 _ 0) -NAMED_CHARACTER_REFERENCE(1465, /* n l */ 'e' _ 's' _ 's' _ ';', 4, 0x226e _ 0) -NAMED_CHARACTER_REFERENCE(1466, /* n l */ 's' _ 'i' _ 'm' _ ';', 4, 0x2274 _ 0) -NAMED_CHARACTER_REFERENCE(1467, /* n l */ 't' _ ';', 2, 0x226e _ 0) -NAMED_CHARACTER_REFERENCE(1468, /* n l */ 't' _ 'r' _ 'i' _ ';', 4, 0x22ea _ 0) -NAMED_CHARACTER_REFERENCE(1469, /* n l */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0x22ec _ 0) -NAMED_CHARACTER_REFERENCE(1470, /* n m */ 'i' _ 'd' _ ';', 3, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(1471, /* n o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5f) -NAMED_CHARACTER_REFERENCE(1472, /* n o */ 't', 1, 0x00ac _ 0) -NAMED_CHARACTER_REFERENCE(1473, /* n o */ 't' _ ';', 2, 0x00ac _ 0) -NAMED_CHARACTER_REFERENCE(1474, /* n o */ 't' _ 'i' _ 'n' _ ';', 4, 0x2209 _ 0) -NAMED_CHARACTER_REFERENCE(1475, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 6, 0x2209 _ 0) -NAMED_CHARACTER_REFERENCE(1476, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 6, 0x22f7 _ 0) -NAMED_CHARACTER_REFERENCE(1477, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 6, 0x22f6 _ 0) -NAMED_CHARACTER_REFERENCE(1478, /* n o */ 't' _ 'n' _ 'i' _ ';', 4, 0x220c _ 0) -NAMED_CHARACTER_REFERENCE(1479, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 6, 0x220c _ 0) -NAMED_CHARACTER_REFERENCE(1480, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 6, 0x22fe _ 0) -NAMED_CHARACTER_REFERENCE(1481, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 6, 0x22fd _ 0) -NAMED_CHARACTER_REFERENCE(1482, /* n p */ 'a' _ 'r' _ ';', 3, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1483, /* n p */ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 8, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1484, /* n p */ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2a14 _ 0) -NAMED_CHARACTER_REFERENCE(1485, /* n p */ 'r' _ ';', 2, 0x2280 _ 0) -NAMED_CHARACTER_REFERENCE(1486, /* n p */ 'r' _ 'c' _ 'u' _ 'e' _ ';', 5, 0x22e0 _ 0) -NAMED_CHARACTER_REFERENCE(1487, /* n p */ 'r' _ 'e' _ 'c' _ ';', 4, 0x2280 _ 0) -NAMED_CHARACTER_REFERENCE(1488, /* n r */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21cf _ 0) -NAMED_CHARACTER_REFERENCE(1489, /* n r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x219b _ 0) -NAMED_CHARACTER_REFERENCE(1490, /* n r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x219b _ 0) -NAMED_CHARACTER_REFERENCE(1491, /* n r */ 't' _ 'r' _ 'i' _ ';', 4, 0x22eb _ 0) -NAMED_CHARACTER_REFERENCE(1492, /* n r */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0x22ed _ 0) -NAMED_CHARACTER_REFERENCE(1493, /* n s */ 'c' _ ';', 2, 0x2281 _ 0) -NAMED_CHARACTER_REFERENCE(1494, /* n s */ 'c' _ 'c' _ 'u' _ 'e' _ ';', 5, 0x22e1 _ 0) -NAMED_CHARACTER_REFERENCE(1495, /* n s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc3) -NAMED_CHARACTER_REFERENCE(1496, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 8, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(1497, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 13, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1498, /* n s */ 'i' _ 'm' _ ';', 3, 0x2241 _ 0) -NAMED_CHARACTER_REFERENCE(1499, /* n s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2244 _ 0) -NAMED_CHARACTER_REFERENCE(1500, /* n s */ 'i' _ 'm' _ 'e' _ 'q' _ ';', 5, 0x2244 _ 0) -NAMED_CHARACTER_REFERENCE(1501, /* n s */ 'm' _ 'i' _ 'd' _ ';', 4, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(1502, /* n s */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1503, /* n s */ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0x22e2 _ 0) -NAMED_CHARACTER_REFERENCE(1504, /* n s */ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0x22e3 _ 0) -NAMED_CHARACTER_REFERENCE(1505, /* n s */ 'u' _ 'b' _ ';', 3, 0x2284 _ 0) -NAMED_CHARACTER_REFERENCE(1506, /* n s */ 'u' _ 'b' _ 'e' _ ';', 4, 0x2288 _ 0) -NAMED_CHARACTER_REFERENCE(1507, /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0x2288 _ 0) -NAMED_CHARACTER_REFERENCE(1508, /* n s */ 'u' _ 'c' _ 'c' _ ';', 4, 0x2281 _ 0) -NAMED_CHARACTER_REFERENCE(1509, /* n s */ 'u' _ 'p' _ ';', 3, 0x2285 _ 0) -NAMED_CHARACTER_REFERENCE(1510, /* n s */ 'u' _ 'p' _ 'e' _ ';', 4, 0x2289 _ 0) -NAMED_CHARACTER_REFERENCE(1511, /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0x2289 _ 0) -NAMED_CHARACTER_REFERENCE(1512, /* n t */ 'g' _ 'l' _ ';', 3, 0x2279 _ 0) -NAMED_CHARACTER_REFERENCE(1513, /* n t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00f1 _ 0) -NAMED_CHARACTER_REFERENCE(1514, /* n t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00f1 _ 0) -NAMED_CHARACTER_REFERENCE(1515, /* n t */ 'l' _ 'g' _ ';', 3, 0x2278 _ 0) -NAMED_CHARACTER_REFERENCE(1516, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0x22ea _ 0) -NAMED_CHARACTER_REFERENCE(1517, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 14, 0x22ec _ 0) -NAMED_CHARACTER_REFERENCE(1518, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0x22eb _ 0) -NAMED_CHARACTER_REFERENCE(1519, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 15, 0x22ed _ 0) -NAMED_CHARACTER_REFERENCE(1520, /* n u */ ';', 1, 0x03bd _ 0) -NAMED_CHARACTER_REFERENCE(1521, /* n u */ 'm' _ ';', 2, 0x0023 _ 0) -NAMED_CHARACTER_REFERENCE(1522, /* n u */ 'm' _ 'e' _ 'r' _ 'o' _ ';', 5, 0x2116 _ 0) -NAMED_CHARACTER_REFERENCE(1523, /* n u */ 'm' _ 's' _ 'p' _ ';', 4, 0x2007 _ 0) -NAMED_CHARACTER_REFERENCE(1524, /* n v */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22ad _ 0) -NAMED_CHARACTER_REFERENCE(1525, /* n v */ 'H' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2904 _ 0) -NAMED_CHARACTER_REFERENCE(1526, /* n v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22ac _ 0) -NAMED_CHARACTER_REFERENCE(1527, /* n v */ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0x29de _ 0) -NAMED_CHARACTER_REFERENCE(1528, /* n v */ 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x2902 _ 0) -NAMED_CHARACTER_REFERENCE(1529, /* n v */ 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x2903 _ 0) -NAMED_CHARACTER_REFERENCE(1530, /* n w */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d6 _ 0) -NAMED_CHARACTER_REFERENCE(1531, /* n w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2923 _ 0) -NAMED_CHARACTER_REFERENCE(1532, /* n w */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2196 _ 0) -NAMED_CHARACTER_REFERENCE(1533, /* n w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2196 _ 0) -NAMED_CHARACTER_REFERENCE(1534, /* n w */ 'n' _ 'e' _ 'a' _ 'r' _ ';', 5, 0x2927 _ 0) -NAMED_CHARACTER_REFERENCE(1535, /* o S */ ';', 1, 0x24c8 _ 0) -NAMED_CHARACTER_REFERENCE(1536, /* o a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00f3 _ 0) -NAMED_CHARACTER_REFERENCE(1537, /* o a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00f3 _ 0) -NAMED_CHARACTER_REFERENCE(1538, /* o a */ 's' _ 't' _ ';', 3, 0x229b _ 0) -NAMED_CHARACTER_REFERENCE(1539, /* o c */ 'i' _ 'r' _ ';', 3, 0x229a _ 0) -NAMED_CHARACTER_REFERENCE(1540, /* o c */ 'i' _ 'r' _ 'c', 3, 0x00f4 _ 0) -NAMED_CHARACTER_REFERENCE(1541, /* o c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00f4 _ 0) -NAMED_CHARACTER_REFERENCE(1542, /* o c */ 'y' _ ';', 2, 0x043e _ 0) -NAMED_CHARACTER_REFERENCE(1543, /* o d */ 'a' _ 's' _ 'h' _ ';', 4, 0x229d _ 0) -NAMED_CHARACTER_REFERENCE(1544, /* o d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0151 _ 0) -NAMED_CHARACTER_REFERENCE(1545, /* o d */ 'i' _ 'v' _ ';', 3, 0x2a38 _ 0) -NAMED_CHARACTER_REFERENCE(1546, /* o d */ 'o' _ 't' _ ';', 3, 0x2299 _ 0) -NAMED_CHARACTER_REFERENCE(1547, /* o d */ 's' _ 'o' _ 'l' _ 'd' _ ';', 5, 0x29bc _ 0) -NAMED_CHARACTER_REFERENCE(1548, /* o e */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0153 _ 0) -NAMED_CHARACTER_REFERENCE(1549, /* o f */ 'c' _ 'i' _ 'r' _ ';', 4, 0x29bf _ 0) -NAMED_CHARACTER_REFERENCE(1550, /* o f */ 'r' _ ';', 2, 0xd835 _ 0xdd2c) -NAMED_CHARACTER_REFERENCE(1551, /* o g */ 'o' _ 'n' _ ';', 3, 0x02db _ 0) -NAMED_CHARACTER_REFERENCE(1552, /* o g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00f2 _ 0) -NAMED_CHARACTER_REFERENCE(1553, /* o g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00f2 _ 0) -NAMED_CHARACTER_REFERENCE(1554, /* o g */ 't' _ ';', 2, 0x29c1 _ 0) -NAMED_CHARACTER_REFERENCE(1555, /* o h */ 'b' _ 'a' _ 'r' _ ';', 4, 0x29b5 _ 0) -NAMED_CHARACTER_REFERENCE(1556, /* o h */ 'm' _ ';', 2, 0x03a9 _ 0) -NAMED_CHARACTER_REFERENCE(1557, /* o i */ 'n' _ 't' _ ';', 3, 0x222e _ 0) -NAMED_CHARACTER_REFERENCE(1558, /* o l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ba _ 0) -NAMED_CHARACTER_REFERENCE(1559, /* o l */ 'c' _ 'i' _ 'r' _ ';', 4, 0x29be _ 0) -NAMED_CHARACTER_REFERENCE(1560, /* o l */ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0x29bb _ 0) -NAMED_CHARACTER_REFERENCE(1561, /* o l */ 'i' _ 'n' _ 'e' _ ';', 4, 0x203e _ 0) -NAMED_CHARACTER_REFERENCE(1562, /* o l */ 't' _ ';', 2, 0x29c0 _ 0) -NAMED_CHARACTER_REFERENCE(1563, /* o m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x014d _ 0) -NAMED_CHARACTER_REFERENCE(1564, /* o m */ 'e' _ 'g' _ 'a' _ ';', 4, 0x03c9 _ 0) -NAMED_CHARACTER_REFERENCE(1565, /* o m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0x03bf _ 0) -NAMED_CHARACTER_REFERENCE(1566, /* o m */ 'i' _ 'd' _ ';', 3, 0x29b6 _ 0) -NAMED_CHARACTER_REFERENCE(1567, /* o m */ 'i' _ 'n' _ 'u' _ 's' _ ';', 5, 0x2296 _ 0) -NAMED_CHARACTER_REFERENCE(1568, /* o o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd60) -NAMED_CHARACTER_REFERENCE(1569, /* o p */ 'a' _ 'r' _ ';', 3, 0x29b7 _ 0) -NAMED_CHARACTER_REFERENCE(1570, /* o p */ 'e' _ 'r' _ 'p' _ ';', 4, 0x29b9 _ 0) -NAMED_CHARACTER_REFERENCE(1571, /* o p */ 'l' _ 'u' _ 's' _ ';', 4, 0x2295 _ 0) -NAMED_CHARACTER_REFERENCE(1572, /* o r */ ';', 1, 0x2228 _ 0) -NAMED_CHARACTER_REFERENCE(1573, /* o r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21bb _ 0) -NAMED_CHARACTER_REFERENCE(1574, /* o r */ 'd' _ ';', 2, 0x2a5d _ 0) -NAMED_CHARACTER_REFERENCE(1575, /* o r */ 'd' _ 'e' _ 'r' _ ';', 4, 0x2134 _ 0) -NAMED_CHARACTER_REFERENCE(1576, /* o r */ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 6, 0x2134 _ 0) -NAMED_CHARACTER_REFERENCE(1577, /* o r */ 'd' _ 'f', 2, 0x00aa _ 0) -NAMED_CHARACTER_REFERENCE(1578, /* o r */ 'd' _ 'f' _ ';', 3, 0x00aa _ 0) -NAMED_CHARACTER_REFERENCE(1579, /* o r */ 'd' _ 'm', 2, 0x00ba _ 0) -NAMED_CHARACTER_REFERENCE(1580, /* o r */ 'd' _ 'm' _ ';', 3, 0x00ba _ 0) -NAMED_CHARACTER_REFERENCE(1581, /* o r */ 'i' _ 'g' _ 'o' _ 'f' _ ';', 5, 0x22b6 _ 0) -NAMED_CHARACTER_REFERENCE(1582, /* o r */ 'o' _ 'r' _ ';', 3, 0x2a56 _ 0) -NAMED_CHARACTER_REFERENCE(1583, /* o r */ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 6, 0x2a57 _ 0) -NAMED_CHARACTER_REFERENCE(1584, /* o r */ 'v' _ ';', 2, 0x2a5b _ 0) -NAMED_CHARACTER_REFERENCE(1585, /* o s */ 'c' _ 'r' _ ';', 3, 0x2134 _ 0) -NAMED_CHARACTER_REFERENCE(1586, /* o s */ 'l' _ 'a' _ 's' _ 'h', 4, 0x00f8 _ 0) -NAMED_CHARACTER_REFERENCE(1587, /* o s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0x00f8 _ 0) -NAMED_CHARACTER_REFERENCE(1588, /* o s */ 'o' _ 'l' _ ';', 3, 0x2298 _ 0) -NAMED_CHARACTER_REFERENCE(1589, /* o t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00f5 _ 0) -NAMED_CHARACTER_REFERENCE(1590, /* o t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00f5 _ 0) -NAMED_CHARACTER_REFERENCE(1591, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x2297 _ 0) -NAMED_CHARACTER_REFERENCE(1592, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 7, 0x2a36 _ 0) -NAMED_CHARACTER_REFERENCE(1593, /* o u */ 'm' _ 'l', 2, 0x00f6 _ 0) -NAMED_CHARACTER_REFERENCE(1594, /* o u */ 'm' _ 'l' _ ';', 3, 0x00f6 _ 0) -NAMED_CHARACTER_REFERENCE(1595, /* o v */ 'b' _ 'a' _ 'r' _ ';', 4, 0x233d _ 0) -NAMED_CHARACTER_REFERENCE(1596, /* p a */ 'r' _ ';', 2, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1597, /* p a */ 'r' _ 'a', 2, 0x00b6 _ 0) -NAMED_CHARACTER_REFERENCE(1598, /* p a */ 'r' _ 'a' _ ';', 3, 0x00b6 _ 0) -NAMED_CHARACTER_REFERENCE(1599, /* p a */ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 7, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1600, /* p a */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2af3 _ 0) -NAMED_CHARACTER_REFERENCE(1601, /* p a */ 'r' _ 's' _ 'l' _ ';', 4, 0x2afd _ 0) -NAMED_CHARACTER_REFERENCE(1602, /* p a */ 'r' _ 't' _ ';', 3, 0x2202 _ 0) -NAMED_CHARACTER_REFERENCE(1603, /* p c */ 'y' _ ';', 2, 0x043f _ 0) -NAMED_CHARACTER_REFERENCE(1604, /* p e */ 'r' _ 'c' _ 'n' _ 't' _ ';', 5, 0x0025 _ 0) -NAMED_CHARACTER_REFERENCE(1605, /* p e */ 'r' _ 'i' _ 'o' _ 'd' _ ';', 5, 0x002e _ 0) -NAMED_CHARACTER_REFERENCE(1606, /* p e */ 'r' _ 'm' _ 'i' _ 'l' _ ';', 5, 0x2030 _ 0) -NAMED_CHARACTER_REFERENCE(1607, /* p e */ 'r' _ 'p' _ ';', 3, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(1608, /* p e */ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 6, 0x2031 _ 0) -NAMED_CHARACTER_REFERENCE(1609, /* p f */ 'r' _ ';', 2, 0xd835 _ 0xdd2d) -NAMED_CHARACTER_REFERENCE(1610, /* p h */ 'i' _ ';', 2, 0x03c6 _ 0) -NAMED_CHARACTER_REFERENCE(1611, /* p h */ 'i' _ 'v' _ ';', 3, 0x03d5 _ 0) -NAMED_CHARACTER_REFERENCE(1612, /* p h */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0x2133 _ 0) -NAMED_CHARACTER_REFERENCE(1613, /* p h */ 'o' _ 'n' _ 'e' _ ';', 4, 0x260e _ 0) -NAMED_CHARACTER_REFERENCE(1614, /* p i */ ';', 1, 0x03c0 _ 0) -NAMED_CHARACTER_REFERENCE(1615, /* p i */ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0x22d4 _ 0) -NAMED_CHARACTER_REFERENCE(1616, /* p i */ 'v' _ ';', 2, 0x03d6 _ 0) -NAMED_CHARACTER_REFERENCE(1617, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ ';', 5, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1618, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 6, 0x210e _ 0) -NAMED_CHARACTER_REFERENCE(1619, /* p l */ 'a' _ 'n' _ 'k' _ 'v' _ ';', 5, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1620, /* p l */ 'u' _ 's' _ ';', 3, 0x002b _ 0) -NAMED_CHARACTER_REFERENCE(1621, /* p l */ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2a23 _ 0) -NAMED_CHARACTER_REFERENCE(1622, /* p l */ 'u' _ 's' _ 'b' _ ';', 4, 0x229e _ 0) -NAMED_CHARACTER_REFERENCE(1623, /* p l */ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2a22 _ 0) -NAMED_CHARACTER_REFERENCE(1624, /* p l */ 'u' _ 's' _ 'd' _ 'o' _ ';', 5, 0x2214 _ 0) -NAMED_CHARACTER_REFERENCE(1625, /* p l */ 'u' _ 's' _ 'd' _ 'u' _ ';', 5, 0x2a25 _ 0) -NAMED_CHARACTER_REFERENCE(1626, /* p l */ 'u' _ 's' _ 'e' _ ';', 4, 0x2a72 _ 0) -NAMED_CHARACTER_REFERENCE(1627, /* p l */ 'u' _ 's' _ 'm' _ 'n', 4, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(1628, /* p l */ 'u' _ 's' _ 'm' _ 'n' _ ';', 5, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(1629, /* p l */ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2a26 _ 0) -NAMED_CHARACTER_REFERENCE(1630, /* p l */ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 6, 0x2a27 _ 0) -NAMED_CHARACTER_REFERENCE(1631, /* p m */ ';', 1, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(1632, /* p o */ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a15 _ 0) -NAMED_CHARACTER_REFERENCE(1633, /* p o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd61) -NAMED_CHARACTER_REFERENCE(1634, /* p o */ 'u' _ 'n' _ 'd', 3, 0x00a3 _ 0) -NAMED_CHARACTER_REFERENCE(1635, /* p o */ 'u' _ 'n' _ 'd' _ ';', 4, 0x00a3 _ 0) -NAMED_CHARACTER_REFERENCE(1636, /* p r */ ';', 1, 0x227a _ 0) -NAMED_CHARACTER_REFERENCE(1637, /* p r */ 'E' _ ';', 2, 0x2ab3 _ 0) -NAMED_CHARACTER_REFERENCE(1638, /* p r */ 'a' _ 'p' _ ';', 3, 0x2ab7 _ 0) -NAMED_CHARACTER_REFERENCE(1639, /* p r */ 'c' _ 'u' _ 'e' _ ';', 4, 0x227c _ 0) -NAMED_CHARACTER_REFERENCE(1640, /* p r */ 'e' _ ';', 2, 0x2aaf _ 0) -NAMED_CHARACTER_REFERENCE(1641, /* p r */ 'e' _ 'c' _ ';', 3, 0x227a _ 0) -NAMED_CHARACTER_REFERENCE(1642, /* p r */ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2ab7 _ 0) -NAMED_CHARACTER_REFERENCE(1643, /* p r */ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0x227c _ 0) -NAMED_CHARACTER_REFERENCE(1644, /* p r */ 'e' _ 'c' _ 'e' _ 'q' _ ';', 5, 0x2aaf _ 0) -NAMED_CHARACTER_REFERENCE(1645, /* p r */ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2ab9 _ 0) -NAMED_CHARACTER_REFERENCE(1646, /* p r */ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0x2ab5 _ 0) -NAMED_CHARACTER_REFERENCE(1647, /* p r */ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0x22e8 _ 0) -NAMED_CHARACTER_REFERENCE(1648, /* p r */ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0x227e _ 0) -NAMED_CHARACTER_REFERENCE(1649, /* p r */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2032 _ 0) -NAMED_CHARACTER_REFERENCE(1650, /* p r */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x2119 _ 0) -NAMED_CHARACTER_REFERENCE(1651, /* p r */ 'n' _ 'E' _ ';', 3, 0x2ab5 _ 0) -NAMED_CHARACTER_REFERENCE(1652, /* p r */ 'n' _ 'a' _ 'p' _ ';', 4, 0x2ab9 _ 0) -NAMED_CHARACTER_REFERENCE(1653, /* p r */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0x22e8 _ 0) -NAMED_CHARACTER_REFERENCE(1654, /* p r */ 'o' _ 'd' _ ';', 3, 0x220f _ 0) -NAMED_CHARACTER_REFERENCE(1655, /* p r */ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 7, 0x232e _ 0) -NAMED_CHARACTER_REFERENCE(1656, /* p r */ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0x2312 _ 0) -NAMED_CHARACTER_REFERENCE(1657, /* p r */ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 7, 0x2313 _ 0) -NAMED_CHARACTER_REFERENCE(1658, /* p r */ 'o' _ 'p' _ ';', 3, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(1659, /* p r */ 'o' _ 'p' _ 't' _ 'o' _ ';', 5, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(1660, /* p r */ 's' _ 'i' _ 'm' _ ';', 4, 0x227e _ 0) -NAMED_CHARACTER_REFERENCE(1661, /* p r */ 'u' _ 'r' _ 'e' _ 'l' _ ';', 5, 0x22b0 _ 0) -NAMED_CHARACTER_REFERENCE(1662, /* p s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc5) -NAMED_CHARACTER_REFERENCE(1663, /* p s */ 'i' _ ';', 2, 0x03c8 _ 0) -NAMED_CHARACTER_REFERENCE(1664, /* p u */ 'n' _ 'c' _ 's' _ 'p' _ ';', 5, 0x2008 _ 0) -NAMED_CHARACTER_REFERENCE(1665, /* q f */ 'r' _ ';', 2, 0xd835 _ 0xdd2e) -NAMED_CHARACTER_REFERENCE(1666, /* q i */ 'n' _ 't' _ ';', 3, 0x2a0c _ 0) -NAMED_CHARACTER_REFERENCE(1667, /* q o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd62) -NAMED_CHARACTER_REFERENCE(1668, /* q p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2057 _ 0) -NAMED_CHARACTER_REFERENCE(1669, /* q s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc6) -NAMED_CHARACTER_REFERENCE(1670, /* q u */ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 10, 0x210d _ 0) -NAMED_CHARACTER_REFERENCE(1671, /* q u */ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2a16 _ 0) -NAMED_CHARACTER_REFERENCE(1672, /* q u */ 'e' _ 's' _ 't' _ ';', 4, 0x003f _ 0) -NAMED_CHARACTER_REFERENCE(1673, /* q u */ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 6, 0x225f _ 0) -NAMED_CHARACTER_REFERENCE(1674, /* q u */ 'o' _ 't', 2, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(1675, /* q u */ 'o' _ 't' _ ';', 3, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(1676, /* r A */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21db _ 0) -NAMED_CHARACTER_REFERENCE(1677, /* r A */ 'r' _ 'r' _ ';', 3, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(1678, /* r A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x291c _ 0) -NAMED_CHARACTER_REFERENCE(1679, /* r B */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290f _ 0) -NAMED_CHARACTER_REFERENCE(1680, /* r H */ 'a' _ 'r' _ ';', 3, 0x2964 _ 0) -NAMED_CHARACTER_REFERENCE(1681, /* r a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0155 _ 0) -NAMED_CHARACTER_REFERENCE(1682, /* r a */ 'd' _ 'i' _ 'c' _ ';', 4, 0x221a _ 0) -NAMED_CHARACTER_REFERENCE(1683, /* r a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0x29b3 _ 0) -NAMED_CHARACTER_REFERENCE(1684, /* r a */ 'n' _ 'g' _ ';', 3, 0x27e9 _ 0) -NAMED_CHARACTER_REFERENCE(1685, /* r a */ 'n' _ 'g' _ 'd' _ ';', 4, 0x2992 _ 0) -NAMED_CHARACTER_REFERENCE(1686, /* r a */ 'n' _ 'g' _ 'e' _ ';', 4, 0x29a5 _ 0) -NAMED_CHARACTER_REFERENCE(1687, /* r a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0x27e9 _ 0) -NAMED_CHARACTER_REFERENCE(1688, /* r a */ 'q' _ 'u' _ 'o', 3, 0x00bb _ 0) -NAMED_CHARACTER_REFERENCE(1689, /* r a */ 'q' _ 'u' _ 'o' _ ';', 4, 0x00bb _ 0) -NAMED_CHARACTER_REFERENCE(1690, /* r a */ 'r' _ 'r' _ ';', 3, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(1691, /* r a */ 'r' _ 'r' _ 'a' _ 'p' _ ';', 5, 0x2975 _ 0) -NAMED_CHARACTER_REFERENCE(1692, /* r a */ 'r' _ 'r' _ 'b' _ ';', 4, 0x21e5 _ 0) -NAMED_CHARACTER_REFERENCE(1693, /* r a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0x2920 _ 0) -NAMED_CHARACTER_REFERENCE(1694, /* r a */ 'r' _ 'r' _ 'c' _ ';', 4, 0x2933 _ 0) -NAMED_CHARACTER_REFERENCE(1695, /* r a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0x291e _ 0) -NAMED_CHARACTER_REFERENCE(1696, /* r a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x21aa _ 0) -NAMED_CHARACTER_REFERENCE(1697, /* r a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0x21ac _ 0) -NAMED_CHARACTER_REFERENCE(1698, /* r a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0x2945 _ 0) -NAMED_CHARACTER_REFERENCE(1699, /* r a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2974 _ 0) -NAMED_CHARACTER_REFERENCE(1700, /* r a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0x21a3 _ 0) -NAMED_CHARACTER_REFERENCE(1701, /* r a */ 'r' _ 'r' _ 'w' _ ';', 4, 0x219d _ 0) -NAMED_CHARACTER_REFERENCE(1702, /* r a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x291a _ 0) -NAMED_CHARACTER_REFERENCE(1703, /* r a */ 't' _ 'i' _ 'o' _ ';', 4, 0x2236 _ 0) -NAMED_CHARACTER_REFERENCE(1704, /* r a */ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ 's' _ ';', 8, 0x211a _ 0) -NAMED_CHARACTER_REFERENCE(1705, /* r b */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290d _ 0) -NAMED_CHARACTER_REFERENCE(1706, /* r b */ 'b' _ 'r' _ 'k' _ ';', 4, 0x2773 _ 0) -NAMED_CHARACTER_REFERENCE(1707, /* r b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0x007d _ 0) -NAMED_CHARACTER_REFERENCE(1708, /* r b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0x005d _ 0) -NAMED_CHARACTER_REFERENCE(1709, /* r b */ 'r' _ 'k' _ 'e' _ ';', 4, 0x298c _ 0) -NAMED_CHARACTER_REFERENCE(1710, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0x298e _ 0) -NAMED_CHARACTER_REFERENCE(1711, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0x2990 _ 0) -NAMED_CHARACTER_REFERENCE(1712, /* r c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0159 _ 0) -NAMED_CHARACTER_REFERENCE(1713, /* r c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0157 _ 0) -NAMED_CHARACTER_REFERENCE(1714, /* r c */ 'e' _ 'i' _ 'l' _ ';', 4, 0x2309 _ 0) -NAMED_CHARACTER_REFERENCE(1715, /* r c */ 'u' _ 'b' _ ';', 3, 0x007d _ 0) -NAMED_CHARACTER_REFERENCE(1716, /* r c */ 'y' _ ';', 2, 0x0440 _ 0) -NAMED_CHARACTER_REFERENCE(1717, /* r d */ 'c' _ 'a' _ ';', 3, 0x2937 _ 0) -NAMED_CHARACTER_REFERENCE(1718, /* r d */ 'l' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2969 _ 0) -NAMED_CHARACTER_REFERENCE(1719, /* r d */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201d _ 0) -NAMED_CHARACTER_REFERENCE(1720, /* r d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x201d _ 0) -NAMED_CHARACTER_REFERENCE(1721, /* r d */ 's' _ 'h' _ ';', 3, 0x21b3 _ 0) -NAMED_CHARACTER_REFERENCE(1722, /* r e */ 'a' _ 'l' _ ';', 3, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(1723, /* r e */ 'a' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0x211b _ 0) -NAMED_CHARACTER_REFERENCE(1724, /* r e */ 'a' _ 'l' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(1725, /* r e */ 'a' _ 'l' _ 's' _ ';', 4, 0x211d _ 0) -NAMED_CHARACTER_REFERENCE(1726, /* r e */ 'c' _ 't' _ ';', 3, 0x25ad _ 0) -NAMED_CHARACTER_REFERENCE(1727, /* r e */ 'g', 1, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(1728, /* r e */ 'g' _ ';', 2, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(1729, /* r f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297d _ 0) -NAMED_CHARACTER_REFERENCE(1730, /* r f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0x230b _ 0) -NAMED_CHARACTER_REFERENCE(1731, /* r f */ 'r' _ ';', 2, 0xd835 _ 0xdd2f) -NAMED_CHARACTER_REFERENCE(1732, /* r h */ 'a' _ 'r' _ 'd' _ ';', 4, 0x21c1 _ 0) -NAMED_CHARACTER_REFERENCE(1733, /* r h */ 'a' _ 'r' _ 'u' _ ';', 4, 0x21c0 _ 0) -NAMED_CHARACTER_REFERENCE(1734, /* r h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0x296c _ 0) -NAMED_CHARACTER_REFERENCE(1735, /* r h */ 'o' _ ';', 2, 0x03c1 _ 0) -NAMED_CHARACTER_REFERENCE(1736, /* r h */ 'o' _ 'v' _ ';', 3, 0x03f1 _ 0) -NAMED_CHARACTER_REFERENCE(1737, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(1738, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 13, 0x21a3 _ 0) -NAMED_CHARACTER_REFERENCE(1739, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 15, 0x21c1 _ 0) -NAMED_CHARACTER_REFERENCE(1740, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 13, 0x21c0 _ 0) -NAMED_CHARACTER_REFERENCE(1741, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0x21c4 _ 0) -NAMED_CHARACTER_REFERENCE(1742, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0x21cc _ 0) -NAMED_CHARACTER_REFERENCE(1743, /* r i */ 'g' _ 'h' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0x21c9 _ 0) -NAMED_CHARACTER_REFERENCE(1744, /* r i */ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x219d _ 0) -NAMED_CHARACTER_REFERENCE(1745, /* r i */ 'g' _ 'h' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 14, 0x22cc _ 0) -NAMED_CHARACTER_REFERENCE(1746, /* r i */ 'n' _ 'g' _ ';', 3, 0x02da _ 0) -NAMED_CHARACTER_REFERENCE(1747, /* r i */ 's' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 11, 0x2253 _ 0) -NAMED_CHARACTER_REFERENCE(1748, /* r l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c4 _ 0) -NAMED_CHARACTER_REFERENCE(1749, /* r l */ 'h' _ 'a' _ 'r' _ ';', 4, 0x21cc _ 0) -NAMED_CHARACTER_REFERENCE(1750, /* r l */ 'm' _ ';', 2, 0x200f _ 0) -NAMED_CHARACTER_REFERENCE(1751, /* r m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0x23b1 _ 0) -NAMED_CHARACTER_REFERENCE(1752, /* r m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0x23b1 _ 0) -NAMED_CHARACTER_REFERENCE(1753, /* r n */ 'm' _ 'i' _ 'd' _ ';', 4, 0x2aee _ 0) -NAMED_CHARACTER_REFERENCE(1754, /* r o */ 'a' _ 'n' _ 'g' _ ';', 4, 0x27ed _ 0) -NAMED_CHARACTER_REFERENCE(1755, /* r o */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21fe _ 0) -NAMED_CHARACTER_REFERENCE(1756, /* r o */ 'b' _ 'r' _ 'k' _ ';', 4, 0x27e7 _ 0) -NAMED_CHARACTER_REFERENCE(1757, /* r o */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2986 _ 0) -NAMED_CHARACTER_REFERENCE(1758, /* r o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd63) -NAMED_CHARACTER_REFERENCE(1759, /* r o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a2e _ 0) -NAMED_CHARACTER_REFERENCE(1760, /* r o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0x2a35 _ 0) -NAMED_CHARACTER_REFERENCE(1761, /* r p */ 'a' _ 'r' _ ';', 3, 0x0029 _ 0) -NAMED_CHARACTER_REFERENCE(1762, /* r p */ 'a' _ 'r' _ 'g' _ 't' _ ';', 5, 0x2994 _ 0) -NAMED_CHARACTER_REFERENCE(1763, /* r p */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a12 _ 0) -NAMED_CHARACTER_REFERENCE(1764, /* r r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c9 _ 0) -NAMED_CHARACTER_REFERENCE(1765, /* r s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0x203a _ 0) -NAMED_CHARACTER_REFERENCE(1766, /* r s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc7) -NAMED_CHARACTER_REFERENCE(1767, /* r s */ 'h' _ ';', 2, 0x21b1 _ 0) -NAMED_CHARACTER_REFERENCE(1768, /* r s */ 'q' _ 'b' _ ';', 3, 0x005d _ 0) -NAMED_CHARACTER_REFERENCE(1769, /* r s */ 'q' _ 'u' _ 'o' _ ';', 4, 0x2019 _ 0) -NAMED_CHARACTER_REFERENCE(1770, /* r s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x2019 _ 0) -NAMED_CHARACTER_REFERENCE(1771, /* r t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0x22cc _ 0) -NAMED_CHARACTER_REFERENCE(1772, /* r t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x22ca _ 0) -NAMED_CHARACTER_REFERENCE(1773, /* r t */ 'r' _ 'i' _ ';', 3, 0x25b9 _ 0) -NAMED_CHARACTER_REFERENCE(1774, /* r t */ 'r' _ 'i' _ 'e' _ ';', 4, 0x22b5 _ 0) -NAMED_CHARACTER_REFERENCE(1775, /* r t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25b8 _ 0) -NAMED_CHARACTER_REFERENCE(1776, /* r t */ 'r' _ 'i' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 7, 0x29ce _ 0) -NAMED_CHARACTER_REFERENCE(1777, /* r u */ 'l' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2968 _ 0) -NAMED_CHARACTER_REFERENCE(1778, /* r x */ ';', 1, 0x211e _ 0) -NAMED_CHARACTER_REFERENCE(1779, /* s a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x015b _ 0) -NAMED_CHARACTER_REFERENCE(1780, /* s b */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201a _ 0) -NAMED_CHARACTER_REFERENCE(1781, /* s c */ ';', 1, 0x227b _ 0) -NAMED_CHARACTER_REFERENCE(1782, /* s c */ 'E' _ ';', 2, 0x2ab4 _ 0) -NAMED_CHARACTER_REFERENCE(1783, /* s c */ 'a' _ 'p' _ ';', 3, 0x2ab8 _ 0) -NAMED_CHARACTER_REFERENCE(1784, /* s c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0161 _ 0) -NAMED_CHARACTER_REFERENCE(1785, /* s c */ 'c' _ 'u' _ 'e' _ ';', 4, 0x227d _ 0) -NAMED_CHARACTER_REFERENCE(1786, /* s c */ 'e' _ ';', 2, 0x2ab0 _ 0) -NAMED_CHARACTER_REFERENCE(1787, /* s c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x015f _ 0) -NAMED_CHARACTER_REFERENCE(1788, /* s c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x015d _ 0) -NAMED_CHARACTER_REFERENCE(1789, /* s c */ 'n' _ 'E' _ ';', 3, 0x2ab6 _ 0) -NAMED_CHARACTER_REFERENCE(1790, /* s c */ 'n' _ 'a' _ 'p' _ ';', 4, 0x2aba _ 0) -NAMED_CHARACTER_REFERENCE(1791, /* s c */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0x22e9 _ 0) -NAMED_CHARACTER_REFERENCE(1792, /* s c */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a13 _ 0) -NAMED_CHARACTER_REFERENCE(1793, /* s c */ 's' _ 'i' _ 'm' _ ';', 4, 0x227f _ 0) -NAMED_CHARACTER_REFERENCE(1794, /* s c */ 'y' _ ';', 2, 0x0441 _ 0) -NAMED_CHARACTER_REFERENCE(1795, /* s d */ 'o' _ 't' _ ';', 3, 0x22c5 _ 0) -NAMED_CHARACTER_REFERENCE(1796, /* s d */ 'o' _ 't' _ 'b' _ ';', 4, 0x22a1 _ 0) -NAMED_CHARACTER_REFERENCE(1797, /* s d */ 'o' _ 't' _ 'e' _ ';', 4, 0x2a66 _ 0) -NAMED_CHARACTER_REFERENCE(1798, /* s e */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d8 _ 0) -NAMED_CHARACTER_REFERENCE(1799, /* s e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2925 _ 0) -NAMED_CHARACTER_REFERENCE(1800, /* s e */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2198 _ 0) -NAMED_CHARACTER_REFERENCE(1801, /* s e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2198 _ 0) -NAMED_CHARACTER_REFERENCE(1802, /* s e */ 'c' _ 't', 2, 0x00a7 _ 0) -NAMED_CHARACTER_REFERENCE(1803, /* s e */ 'c' _ 't' _ ';', 3, 0x00a7 _ 0) -NAMED_CHARACTER_REFERENCE(1804, /* s e */ 'm' _ 'i' _ ';', 3, 0x003b _ 0) -NAMED_CHARACTER_REFERENCE(1805, /* s e */ 's' _ 'w' _ 'a' _ 'r' _ ';', 5, 0x2929 _ 0) -NAMED_CHARACTER_REFERENCE(1806, /* s e */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1807, /* s e */ 't' _ 'm' _ 'n' _ ';', 4, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1808, /* s e */ 'x' _ 't' _ ';', 3, 0x2736 _ 0) -NAMED_CHARACTER_REFERENCE(1809, /* s f */ 'r' _ ';', 2, 0xd835 _ 0xdd30) -NAMED_CHARACTER_REFERENCE(1810, /* s f */ 'r' _ 'o' _ 'w' _ 'n' _ ';', 5, 0x2322 _ 0) -NAMED_CHARACTER_REFERENCE(1811, /* s h */ 'a' _ 'r' _ 'p' _ ';', 4, 0x266f _ 0) -NAMED_CHARACTER_REFERENCE(1812, /* s h */ 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0449 _ 0) -NAMED_CHARACTER_REFERENCE(1813, /* s h */ 'c' _ 'y' _ ';', 3, 0x0448 _ 0) -NAMED_CHARACTER_REFERENCE(1814, /* s h */ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 7, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(1815, /* s h */ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 12, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1816, /* s h */ 'y', 1, 0x00ad _ 0) -NAMED_CHARACTER_REFERENCE(1817, /* s h */ 'y' _ ';', 2, 0x00ad _ 0) -NAMED_CHARACTER_REFERENCE(1818, /* s i */ 'g' _ 'm' _ 'a' _ ';', 4, 0x03c3 _ 0) -NAMED_CHARACTER_REFERENCE(1819, /* s i */ 'g' _ 'm' _ 'a' _ 'f' _ ';', 5, 0x03c2 _ 0) -NAMED_CHARACTER_REFERENCE(1820, /* s i */ 'g' _ 'm' _ 'a' _ 'v' _ ';', 5, 0x03c2 _ 0) -NAMED_CHARACTER_REFERENCE(1821, /* s i */ 'm' _ ';', 2, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(1822, /* s i */ 'm' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a6a _ 0) -NAMED_CHARACTER_REFERENCE(1823, /* s i */ 'm' _ 'e' _ ';', 3, 0x2243 _ 0) -NAMED_CHARACTER_REFERENCE(1824, /* s i */ 'm' _ 'e' _ 'q' _ ';', 4, 0x2243 _ 0) -NAMED_CHARACTER_REFERENCE(1825, /* s i */ 'm' _ 'g' _ ';', 3, 0x2a9e _ 0) -NAMED_CHARACTER_REFERENCE(1826, /* s i */ 'm' _ 'g' _ 'E' _ ';', 4, 0x2aa0 _ 0) -NAMED_CHARACTER_REFERENCE(1827, /* s i */ 'm' _ 'l' _ ';', 3, 0x2a9d _ 0) -NAMED_CHARACTER_REFERENCE(1828, /* s i */ 'm' _ 'l' _ 'E' _ ';', 4, 0x2a9f _ 0) -NAMED_CHARACTER_REFERENCE(1829, /* s i */ 'm' _ 'n' _ 'e' _ ';', 4, 0x2246 _ 0) -NAMED_CHARACTER_REFERENCE(1830, /* s i */ 'm' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2a24 _ 0) -NAMED_CHARACTER_REFERENCE(1831, /* s i */ 'm' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2972 _ 0) -NAMED_CHARACTER_REFERENCE(1832, /* s l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(1833, /* s m */ 'a' _ 'l' _ 'l' _ 's' _ 'e' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 12, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1834, /* s m */ 'a' _ 's' _ 'h' _ 'p' _ ';', 5, 0x2a33 _ 0) -NAMED_CHARACTER_REFERENCE(1835, /* s m */ 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0x29e4 _ 0) -NAMED_CHARACTER_REFERENCE(1836, /* s m */ 'i' _ 'd' _ ';', 3, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(1837, /* s m */ 'i' _ 'l' _ 'e' _ ';', 4, 0x2323 _ 0) -NAMED_CHARACTER_REFERENCE(1838, /* s m */ 't' _ ';', 2, 0x2aaa _ 0) -NAMED_CHARACTER_REFERENCE(1839, /* s m */ 't' _ 'e' _ ';', 3, 0x2aac _ 0) -NAMED_CHARACTER_REFERENCE(1840, /* s o */ 'f' _ 't' _ 'c' _ 'y' _ ';', 5, 0x044c _ 0) -NAMED_CHARACTER_REFERENCE(1841, /* s o */ 'l' _ ';', 2, 0x002f _ 0) -NAMED_CHARACTER_REFERENCE(1842, /* s o */ 'l' _ 'b' _ ';', 3, 0x29c4 _ 0) -NAMED_CHARACTER_REFERENCE(1843, /* s o */ 'l' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x233f _ 0) -NAMED_CHARACTER_REFERENCE(1844, /* s o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd64) -NAMED_CHARACTER_REFERENCE(1845, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ ';', 5, 0x2660 _ 0) -NAMED_CHARACTER_REFERENCE(1846, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0x2660 _ 0) -NAMED_CHARACTER_REFERENCE(1847, /* s p */ 'a' _ 'r' _ ';', 3, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1848, /* s q */ 'c' _ 'a' _ 'p' _ ';', 4, 0x2293 _ 0) -NAMED_CHARACTER_REFERENCE(1849, /* s q */ 'c' _ 'u' _ 'p' _ ';', 4, 0x2294 _ 0) -NAMED_CHARACTER_REFERENCE(1850, /* s q */ 's' _ 'u' _ 'b' _ ';', 4, 0x228f _ 0) -NAMED_CHARACTER_REFERENCE(1851, /* s q */ 's' _ 'u' _ 'b' _ 'e' _ ';', 5, 0x2291 _ 0) -NAMED_CHARACTER_REFERENCE(1852, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 7, 0x228f _ 0) -NAMED_CHARACTER_REFERENCE(1853, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0x2291 _ 0) -NAMED_CHARACTER_REFERENCE(1854, /* s q */ 's' _ 'u' _ 'p' _ ';', 4, 0x2290 _ 0) -NAMED_CHARACTER_REFERENCE(1855, /* s q */ 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0x2292 _ 0) -NAMED_CHARACTER_REFERENCE(1856, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, 0x2290 _ 0) -NAMED_CHARACTER_REFERENCE(1857, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0x2292 _ 0) -NAMED_CHARACTER_REFERENCE(1858, /* s q */ 'u' _ ';', 2, 0x25a1 _ 0) -NAMED_CHARACTER_REFERENCE(1859, /* s q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0x25a1 _ 0) -NAMED_CHARACTER_REFERENCE(1860, /* s q */ 'u' _ 'a' _ 'r' _ 'f' _ ';', 5, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(1861, /* s q */ 'u' _ 'f' _ ';', 3, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(1862, /* s r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(1863, /* s s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc8) -NAMED_CHARACTER_REFERENCE(1864, /* s s */ 'e' _ 't' _ 'm' _ 'n' _ ';', 5, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1865, /* s s */ 'm' _ 'i' _ 'l' _ 'e' _ ';', 5, 0x2323 _ 0) -NAMED_CHARACTER_REFERENCE(1866, /* s s */ 't' _ 'a' _ 'r' _ 'f' _ ';', 5, 0x22c6 _ 0) -NAMED_CHARACTER_REFERENCE(1867, /* s t */ 'a' _ 'r' _ ';', 3, 0x2606 _ 0) -NAMED_CHARACTER_REFERENCE(1868, /* s t */ 'a' _ 'r' _ 'f' _ ';', 4, 0x2605 _ 0) -NAMED_CHARACTER_REFERENCE(1869, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 14, 0x03f5 _ 0) -NAMED_CHARACTER_REFERENCE(1870, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'p' _ 'h' _ 'i' _ ';', 10, 0x03d5 _ 0) -NAMED_CHARACTER_REFERENCE(1871, /* s t */ 'r' _ 'n' _ 's' _ ';', 4, 0x00af _ 0) -NAMED_CHARACTER_REFERENCE(1872, /* s u */ 'b' _ ';', 2, 0x2282 _ 0) -NAMED_CHARACTER_REFERENCE(1873, /* s u */ 'b' _ 'E' _ ';', 3, 0x2ac5 _ 0) -NAMED_CHARACTER_REFERENCE(1874, /* s u */ 'b' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2abd _ 0) -NAMED_CHARACTER_REFERENCE(1875, /* s u */ 'b' _ 'e' _ ';', 3, 0x2286 _ 0) -NAMED_CHARACTER_REFERENCE(1876, /* s u */ 'b' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2ac3 _ 0) -NAMED_CHARACTER_REFERENCE(1877, /* s u */ 'b' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0x2ac1 _ 0) -NAMED_CHARACTER_REFERENCE(1878, /* s u */ 'b' _ 'n' _ 'E' _ ';', 4, 0x2acb _ 0) -NAMED_CHARACTER_REFERENCE(1879, /* s u */ 'b' _ 'n' _ 'e' _ ';', 4, 0x228a _ 0) -NAMED_CHARACTER_REFERENCE(1880, /* s u */ 'b' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2abf _ 0) -NAMED_CHARACTER_REFERENCE(1881, /* s u */ 'b' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2979 _ 0) -NAMED_CHARACTER_REFERENCE(1882, /* s u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0x2282 _ 0) -NAMED_CHARACTER_REFERENCE(1883, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0x2286 _ 0) -NAMED_CHARACTER_REFERENCE(1884, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0x2ac5 _ 0) -NAMED_CHARACTER_REFERENCE(1885, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0x228a _ 0) -NAMED_CHARACTER_REFERENCE(1886, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0x2acb _ 0) -NAMED_CHARACTER_REFERENCE(1887, /* s u */ 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2ac7 _ 0) -NAMED_CHARACTER_REFERENCE(1888, /* s u */ 'b' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2ad5 _ 0) -NAMED_CHARACTER_REFERENCE(1889, /* s u */ 'b' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2ad3 _ 0) -NAMED_CHARACTER_REFERENCE(1890, /* s u */ 'c' _ 'c' _ ';', 3, 0x227b _ 0) -NAMED_CHARACTER_REFERENCE(1891, /* s u */ 'c' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2ab8 _ 0) -NAMED_CHARACTER_REFERENCE(1892, /* s u */ 'c' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0x227d _ 0) -NAMED_CHARACTER_REFERENCE(1893, /* s u */ 'c' _ 'c' _ 'e' _ 'q' _ ';', 5, 0x2ab0 _ 0) -NAMED_CHARACTER_REFERENCE(1894, /* s u */ 'c' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2aba _ 0) -NAMED_CHARACTER_REFERENCE(1895, /* s u */ 'c' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0x2ab6 _ 0) -NAMED_CHARACTER_REFERENCE(1896, /* s u */ 'c' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0x22e9 _ 0) -NAMED_CHARACTER_REFERENCE(1897, /* s u */ 'c' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0x227f _ 0) -NAMED_CHARACTER_REFERENCE(1898, /* s u */ 'm' _ ';', 2, 0x2211 _ 0) -NAMED_CHARACTER_REFERENCE(1899, /* s u */ 'n' _ 'g' _ ';', 3, 0x266a _ 0) -NAMED_CHARACTER_REFERENCE(1900, /* s u */ 'p' _ '1', 2, 0x00b9 _ 0) -NAMED_CHARACTER_REFERENCE(1901, /* s u */ 'p' _ '1' _ ';', 3, 0x00b9 _ 0) -NAMED_CHARACTER_REFERENCE(1902, /* s u */ 'p' _ '2', 2, 0x00b2 _ 0) -NAMED_CHARACTER_REFERENCE(1903, /* s u */ 'p' _ '2' _ ';', 3, 0x00b2 _ 0) -NAMED_CHARACTER_REFERENCE(1904, /* s u */ 'p' _ '3', 2, 0x00b3 _ 0) -NAMED_CHARACTER_REFERENCE(1905, /* s u */ 'p' _ '3' _ ';', 3, 0x00b3 _ 0) -NAMED_CHARACTER_REFERENCE(1906, /* s u */ 'p' _ ';', 2, 0x2283 _ 0) -NAMED_CHARACTER_REFERENCE(1907, /* s u */ 'p' _ 'E' _ ';', 3, 0x2ac6 _ 0) -NAMED_CHARACTER_REFERENCE(1908, /* s u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2abe _ 0) -NAMED_CHARACTER_REFERENCE(1909, /* s u */ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 6, 0x2ad8 _ 0) -NAMED_CHARACTER_REFERENCE(1910, /* s u */ 'p' _ 'e' _ ';', 3, 0x2287 _ 0) -NAMED_CHARACTER_REFERENCE(1911, /* s u */ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2ac4 _ 0) -NAMED_CHARACTER_REFERENCE(1912, /* s u */ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 6, 0x27c9 _ 0) -NAMED_CHARACTER_REFERENCE(1913, /* s u */ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 6, 0x2ad7 _ 0) -NAMED_CHARACTER_REFERENCE(1914, /* s u */ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x297b _ 0) -NAMED_CHARACTER_REFERENCE(1915, /* s u */ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0x2ac2 _ 0) -NAMED_CHARACTER_REFERENCE(1916, /* s u */ 'p' _ 'n' _ 'E' _ ';', 4, 0x2acc _ 0) -NAMED_CHARACTER_REFERENCE(1917, /* s u */ 'p' _ 'n' _ 'e' _ ';', 4, 0x228b _ 0) -NAMED_CHARACTER_REFERENCE(1918, /* s u */ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2ac0 _ 0) -NAMED_CHARACTER_REFERENCE(1919, /* s u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0x2283 _ 0) -NAMED_CHARACTER_REFERENCE(1920, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0x2287 _ 0) -NAMED_CHARACTER_REFERENCE(1921, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0x2ac6 _ 0) -NAMED_CHARACTER_REFERENCE(1922, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0x228b _ 0) -NAMED_CHARACTER_REFERENCE(1923, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0x2acc _ 0) -NAMED_CHARACTER_REFERENCE(1924, /* s u */ 'p' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2ac8 _ 0) -NAMED_CHARACTER_REFERENCE(1925, /* s u */ 'p' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2ad4 _ 0) -NAMED_CHARACTER_REFERENCE(1926, /* s u */ 'p' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2ad6 _ 0) -NAMED_CHARACTER_REFERENCE(1927, /* s w */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d9 _ 0) -NAMED_CHARACTER_REFERENCE(1928, /* s w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2926 _ 0) -NAMED_CHARACTER_REFERENCE(1929, /* s w */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2199 _ 0) -NAMED_CHARACTER_REFERENCE(1930, /* s w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2199 _ 0) -NAMED_CHARACTER_REFERENCE(1931, /* s w */ 'n' _ 'w' _ 'a' _ 'r' _ ';', 5, 0x292a _ 0) -NAMED_CHARACTER_REFERENCE(1932, /* s z */ 'l' _ 'i' _ 'g', 3, 0x00df _ 0) -NAMED_CHARACTER_REFERENCE(1933, /* s z */ 'l' _ 'i' _ 'g' _ ';', 4, 0x00df _ 0) -NAMED_CHARACTER_REFERENCE(1934, /* t a */ 'r' _ 'g' _ 'e' _ 't' _ ';', 5, 0x2316 _ 0) -NAMED_CHARACTER_REFERENCE(1935, /* t a */ 'u' _ ';', 2, 0x03c4 _ 0) -NAMED_CHARACTER_REFERENCE(1936, /* t b */ 'r' _ 'k' _ ';', 3, 0x23b4 _ 0) -NAMED_CHARACTER_REFERENCE(1937, /* t c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0165 _ 0) -NAMED_CHARACTER_REFERENCE(1938, /* t c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0163 _ 0) -NAMED_CHARACTER_REFERENCE(1939, /* t c */ 'y' _ ';', 2, 0x0442 _ 0) -NAMED_CHARACTER_REFERENCE(1940, /* t d */ 'o' _ 't' _ ';', 3, 0x20db _ 0) -NAMED_CHARACTER_REFERENCE(1941, /* t e */ 'l' _ 'r' _ 'e' _ 'c' _ ';', 5, 0x2315 _ 0) -NAMED_CHARACTER_REFERENCE(1942, /* t f */ 'r' _ ';', 2, 0xd835 _ 0xdd31) -NAMED_CHARACTER_REFERENCE(1943, /* t h */ 'e' _ 'r' _ 'e' _ '4' _ ';', 5, 0x2234 _ 0) -NAMED_CHARACTER_REFERENCE(1944, /* t h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0x2234 _ 0) -NAMED_CHARACTER_REFERENCE(1945, /* t h */ 'e' _ 't' _ 'a' _ ';', 4, 0x03b8 _ 0) -NAMED_CHARACTER_REFERENCE(1946, /* t h */ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 7, 0x03d1 _ 0) -NAMED_CHARACTER_REFERENCE(1947, /* t h */ 'e' _ 't' _ 'a' _ 'v' _ ';', 5, 0x03d1 _ 0) -NAMED_CHARACTER_REFERENCE(1948, /* t h */ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(1949, /* t h */ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(1950, /* t h */ 'i' _ 'n' _ 's' _ 'p' _ ';', 5, 0x2009 _ 0) -NAMED_CHARACTER_REFERENCE(1951, /* t h */ 'k' _ 'a' _ 'p' _ ';', 4, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(1952, /* t h */ 'k' _ 's' _ 'i' _ 'm' _ ';', 5, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(1953, /* t h */ 'o' _ 'r' _ 'n', 3, 0x00fe _ 0) -NAMED_CHARACTER_REFERENCE(1954, /* t h */ 'o' _ 'r' _ 'n' _ ';', 4, 0x00fe _ 0) -NAMED_CHARACTER_REFERENCE(1955, /* t i */ 'l' _ 'd' _ 'e' _ ';', 4, 0x02dc _ 0) -NAMED_CHARACTER_REFERENCE(1956, /* t i */ 'm' _ 'e' _ 's', 3, 0x00d7 _ 0) -NAMED_CHARACTER_REFERENCE(1957, /* t i */ 'm' _ 'e' _ 's' _ ';', 4, 0x00d7 _ 0) -NAMED_CHARACTER_REFERENCE(1958, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ ';', 5, 0x22a0 _ 0) -NAMED_CHARACTER_REFERENCE(1959, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x2a31 _ 0) -NAMED_CHARACTER_REFERENCE(1960, /* t i */ 'm' _ 'e' _ 's' _ 'd' _ ';', 5, 0x2a30 _ 0) -NAMED_CHARACTER_REFERENCE(1961, /* t i */ 'n' _ 't' _ ';', 3, 0x222d _ 0) -NAMED_CHARACTER_REFERENCE(1962, /* t o */ 'e' _ 'a' _ ';', 3, 0x2928 _ 0) -NAMED_CHARACTER_REFERENCE(1963, /* t o */ 'p' _ ';', 2, 0x22a4 _ 0) -NAMED_CHARACTER_REFERENCE(1964, /* t o */ 'p' _ 'b' _ 'o' _ 't' _ ';', 5, 0x2336 _ 0) -NAMED_CHARACTER_REFERENCE(1965, /* t o */ 'p' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2af1 _ 0) -NAMED_CHARACTER_REFERENCE(1966, /* t o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd65) -NAMED_CHARACTER_REFERENCE(1967, /* t o */ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 6, 0x2ada _ 0) -NAMED_CHARACTER_REFERENCE(1968, /* t o */ 's' _ 'a' _ ';', 3, 0x2929 _ 0) -NAMED_CHARACTER_REFERENCE(1969, /* t p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2034 _ 0) -NAMED_CHARACTER_REFERENCE(1970, /* t r */ 'a' _ 'd' _ 'e' _ ';', 4, 0x2122 _ 0) -NAMED_CHARACTER_REFERENCE(1971, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, 0x25b5 _ 0) -NAMED_CHARACTER_REFERENCE(1972, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 11, 0x25bf _ 0) -NAMED_CHARACTER_REFERENCE(1973, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 11, 0x25c3 _ 0) -NAMED_CHARACTER_REFERENCE(1974, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 13, 0x22b4 _ 0) -NAMED_CHARACTER_REFERENCE(1975, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 8, 0x225c _ 0) -NAMED_CHARACTER_REFERENCE(1976, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 12, 0x25b9 _ 0) -NAMED_CHARACTER_REFERENCE(1977, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 14, 0x22b5 _ 0) -NAMED_CHARACTER_REFERENCE(1978, /* t r */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0x25ec _ 0) -NAMED_CHARACTER_REFERENCE(1979, /* t r */ 'i' _ 'e' _ ';', 3, 0x225c _ 0) -NAMED_CHARACTER_REFERENCE(1980, /* t r */ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2a3a _ 0) -NAMED_CHARACTER_REFERENCE(1981, /* t r */ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2a39 _ 0) -NAMED_CHARACTER_REFERENCE(1982, /* t r */ 'i' _ 's' _ 'b' _ ';', 4, 0x29cd _ 0) -NAMED_CHARACTER_REFERENCE(1983, /* t r */ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2a3b _ 0) -NAMED_CHARACTER_REFERENCE(1984, /* t r */ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 7, 0x23e2 _ 0) -NAMED_CHARACTER_REFERENCE(1985, /* t s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc9) -NAMED_CHARACTER_REFERENCE(1986, /* t s */ 'c' _ 'y' _ ';', 3, 0x0446 _ 0) -NAMED_CHARACTER_REFERENCE(1987, /* t s */ 'h' _ 'c' _ 'y' _ ';', 4, 0x045b _ 0) -NAMED_CHARACTER_REFERENCE(1988, /* t s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0167 _ 0) -NAMED_CHARACTER_REFERENCE(1989, /* t w */ 'i' _ 'x' _ 't' _ ';', 4, 0x226c _ 0) -NAMED_CHARACTER_REFERENCE(1990, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x219e _ 0) -NAMED_CHARACTER_REFERENCE(1991, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21a0 _ 0) -NAMED_CHARACTER_REFERENCE(1992, /* u A */ 'r' _ 'r' _ ';', 3, 0x21d1 _ 0) -NAMED_CHARACTER_REFERENCE(1993, /* u H */ 'a' _ 'r' _ ';', 3, 0x2963 _ 0) -NAMED_CHARACTER_REFERENCE(1994, /* u a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00fa _ 0) -NAMED_CHARACTER_REFERENCE(1995, /* u a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00fa _ 0) -NAMED_CHARACTER_REFERENCE(1996, /* u a */ 'r' _ 'r' _ ';', 3, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(1997, /* u b */ 'r' _ 'c' _ 'y' _ ';', 4, 0x045e _ 0) -NAMED_CHARACTER_REFERENCE(1998, /* u b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x016d _ 0) -NAMED_CHARACTER_REFERENCE(1999, /* u c */ 'i' _ 'r' _ 'c', 3, 0x00fb _ 0) -NAMED_CHARACTER_REFERENCE(2000, /* u c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00fb _ 0) -NAMED_CHARACTER_REFERENCE(2001, /* u c */ 'y' _ ';', 2, 0x0443 _ 0) -NAMED_CHARACTER_REFERENCE(2002, /* u d */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c5 _ 0) -NAMED_CHARACTER_REFERENCE(2003, /* u d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0171 _ 0) -NAMED_CHARACTER_REFERENCE(2004, /* u d */ 'h' _ 'a' _ 'r' _ ';', 4, 0x296e _ 0) -NAMED_CHARACTER_REFERENCE(2005, /* u f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297e _ 0) -NAMED_CHARACTER_REFERENCE(2006, /* u f */ 'r' _ ';', 2, 0xd835 _ 0xdd32) -NAMED_CHARACTER_REFERENCE(2007, /* u g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00f9 _ 0) -NAMED_CHARACTER_REFERENCE(2008, /* u g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00f9 _ 0) -NAMED_CHARACTER_REFERENCE(2009, /* u h */ 'a' _ 'r' _ 'l' _ ';', 4, 0x21bf _ 0) -NAMED_CHARACTER_REFERENCE(2010, /* u h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21be _ 0) -NAMED_CHARACTER_REFERENCE(2011, /* u h */ 'b' _ 'l' _ 'k' _ ';', 4, 0x2580 _ 0) -NAMED_CHARACTER_REFERENCE(2012, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231c _ 0) -NAMED_CHARACTER_REFERENCE(2013, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231c _ 0) -NAMED_CHARACTER_REFERENCE(2014, /* u l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230f _ 0) -NAMED_CHARACTER_REFERENCE(2015, /* u l */ 't' _ 'r' _ 'i' _ ';', 4, 0x25f8 _ 0) -NAMED_CHARACTER_REFERENCE(2016, /* u m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x016b _ 0) -NAMED_CHARACTER_REFERENCE(2017, /* u m */ 'l', 1, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(2018, /* u m */ 'l' _ ';', 2, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(2019, /* u o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0173 _ 0) -NAMED_CHARACTER_REFERENCE(2020, /* u o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd66) -NAMED_CHARACTER_REFERENCE(2021, /* u p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(2022, /* u p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2195 _ 0) -NAMED_CHARACTER_REFERENCE(2023, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0x21bf _ 0) -NAMED_CHARACTER_REFERENCE(2024, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0x21be _ 0) -NAMED_CHARACTER_REFERENCE(2025, /* u p */ 'l' _ 'u' _ 's' _ ';', 4, 0x228e _ 0) -NAMED_CHARACTER_REFERENCE(2026, /* u p */ 's' _ 'i' _ ';', 3, 0x03c5 _ 0) -NAMED_CHARACTER_REFERENCE(2027, /* u p */ 's' _ 'i' _ 'h' _ ';', 4, 0x03d2 _ 0) -NAMED_CHARACTER_REFERENCE(2028, /* u p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x03c5 _ 0) -NAMED_CHARACTER_REFERENCE(2029, /* u p */ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 9, 0x21c8 _ 0) -NAMED_CHARACTER_REFERENCE(2030, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231d _ 0) -NAMED_CHARACTER_REFERENCE(2031, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231d _ 0) -NAMED_CHARACTER_REFERENCE(2032, /* u r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230e _ 0) -NAMED_CHARACTER_REFERENCE(2033, /* u r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x016f _ 0) -NAMED_CHARACTER_REFERENCE(2034, /* u r */ 't' _ 'r' _ 'i' _ ';', 4, 0x25f9 _ 0) -NAMED_CHARACTER_REFERENCE(2035, /* u s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcca) -NAMED_CHARACTER_REFERENCE(2036, /* u t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22f0 _ 0) -NAMED_CHARACTER_REFERENCE(2037, /* u t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0169 _ 0) -NAMED_CHARACTER_REFERENCE(2038, /* u t */ 'r' _ 'i' _ ';', 3, 0x25b5 _ 0) -NAMED_CHARACTER_REFERENCE(2039, /* u t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25b4 _ 0) -NAMED_CHARACTER_REFERENCE(2040, /* u u */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c8 _ 0) -NAMED_CHARACTER_REFERENCE(2041, /* u u */ 'm' _ 'l', 2, 0x00fc _ 0) -NAMED_CHARACTER_REFERENCE(2042, /* u u */ 'm' _ 'l' _ ';', 3, 0x00fc _ 0) -NAMED_CHARACTER_REFERENCE(2043, /* u w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0x29a7 _ 0) -NAMED_CHARACTER_REFERENCE(2044, /* v A */ 'r' _ 'r' _ ';', 3, 0x21d5 _ 0) -NAMED_CHARACTER_REFERENCE(2045, /* v B */ 'a' _ 'r' _ ';', 3, 0x2ae8 _ 0) -NAMED_CHARACTER_REFERENCE(2046, /* v B */ 'a' _ 'r' _ 'v' _ ';', 4, 0x2ae9 _ 0) -NAMED_CHARACTER_REFERENCE(2047, /* v D */ 'a' _ 's' _ 'h' _ ';', 4, 0x22a8 _ 0) -NAMED_CHARACTER_REFERENCE(2048, /* v a */ 'n' _ 'g' _ 'r' _ 't' _ ';', 5, 0x299c _ 0) -NAMED_CHARACTER_REFERENCE(2049, /* v a */ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 9, 0x03f5 _ 0) -NAMED_CHARACTER_REFERENCE(2050, /* v a */ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 7, 0x03f0 _ 0) -NAMED_CHARACTER_REFERENCE(2051, /* v a */ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 9, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(2052, /* v a */ 'r' _ 'p' _ 'h' _ 'i' _ ';', 5, 0x03d5 _ 0) -NAMED_CHARACTER_REFERENCE(2053, /* v a */ 'r' _ 'p' _ 'i' _ ';', 4, 0x03d6 _ 0) -NAMED_CHARACTER_REFERENCE(2054, /* v a */ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 8, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(2055, /* v a */ 'r' _ 'r' _ ';', 3, 0x2195 _ 0) -NAMED_CHARACTER_REFERENCE(2056, /* v a */ 'r' _ 'r' _ 'h' _ 'o' _ ';', 5, 0x03f1 _ 0) -NAMED_CHARACTER_REFERENCE(2057, /* v a */ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 7, 0x03c2 _ 0) -NAMED_CHARACTER_REFERENCE(2058, /* v a */ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 7, 0x03d1 _ 0) -NAMED_CHARACTER_REFERENCE(2059, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x22b2 _ 0) -NAMED_CHARACTER_REFERENCE(2060, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x22b3 _ 0) -NAMED_CHARACTER_REFERENCE(2061, /* v c */ 'y' _ ';', 2, 0x0432 _ 0) -NAMED_CHARACTER_REFERENCE(2062, /* v d */ 'a' _ 's' _ 'h' _ ';', 4, 0x22a2 _ 0) -NAMED_CHARACTER_REFERENCE(2063, /* v e */ 'e' _ ';', 2, 0x2228 _ 0) -NAMED_CHARACTER_REFERENCE(2064, /* v e */ 'e' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x22bb _ 0) -NAMED_CHARACTER_REFERENCE(2065, /* v e */ 'e' _ 'e' _ 'q' _ ';', 4, 0x225a _ 0) -NAMED_CHARACTER_REFERENCE(2066, /* v e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0x22ee _ 0) -NAMED_CHARACTER_REFERENCE(2067, /* v e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x007c _ 0) -NAMED_CHARACTER_REFERENCE(2068, /* v e */ 'r' _ 't' _ ';', 3, 0x007c _ 0) -NAMED_CHARACTER_REFERENCE(2069, /* v f */ 'r' _ ';', 2, 0xd835 _ 0xdd33) -NAMED_CHARACTER_REFERENCE(2070, /* v l */ 't' _ 'r' _ 'i' _ ';', 4, 0x22b2 _ 0) -NAMED_CHARACTER_REFERENCE(2071, /* v o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd67) -NAMED_CHARACTER_REFERENCE(2072, /* v p */ 'r' _ 'o' _ 'p' _ ';', 4, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(2073, /* v r */ 't' _ 'r' _ 'i' _ ';', 4, 0x22b3 _ 0) -NAMED_CHARACTER_REFERENCE(2074, /* v s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccb) -NAMED_CHARACTER_REFERENCE(2075, /* v z */ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 6, 0x299a _ 0) -NAMED_CHARACTER_REFERENCE(2076, /* w c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0175 _ 0) -NAMED_CHARACTER_REFERENCE(2077, /* w e */ 'd' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x2a5f _ 0) -NAMED_CHARACTER_REFERENCE(2078, /* w e */ 'd' _ 'g' _ 'e' _ ';', 4, 0x2227 _ 0) -NAMED_CHARACTER_REFERENCE(2079, /* w e */ 'd' _ 'g' _ 'e' _ 'q' _ ';', 5, 0x2259 _ 0) -NAMED_CHARACTER_REFERENCE(2080, /* w e */ 'i' _ 'e' _ 'r' _ 'p' _ ';', 5, 0x2118 _ 0) -NAMED_CHARACTER_REFERENCE(2081, /* w f */ 'r' _ ';', 2, 0xd835 _ 0xdd34) -NAMED_CHARACTER_REFERENCE(2082, /* w o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd68) -NAMED_CHARACTER_REFERENCE(2083, /* w p */ ';', 1, 0x2118 _ 0) -NAMED_CHARACTER_REFERENCE(2084, /* w r */ ';', 1, 0x2240 _ 0) -NAMED_CHARACTER_REFERENCE(2085, /* w r */ 'e' _ 'a' _ 't' _ 'h' _ ';', 5, 0x2240 _ 0) -NAMED_CHARACTER_REFERENCE(2086, /* w s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccc) -NAMED_CHARACTER_REFERENCE(2087, /* x c */ 'a' _ 'p' _ ';', 3, 0x22c2 _ 0) -NAMED_CHARACTER_REFERENCE(2088, /* x c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x25ef _ 0) -NAMED_CHARACTER_REFERENCE(2089, /* x c */ 'u' _ 'p' _ ';', 3, 0x22c3 _ 0) -NAMED_CHARACTER_REFERENCE(2090, /* x d */ 't' _ 'r' _ 'i' _ ';', 4, 0x25bd _ 0) -NAMED_CHARACTER_REFERENCE(2091, /* x f */ 'r' _ ';', 2, 0xd835 _ 0xdd35) -NAMED_CHARACTER_REFERENCE(2092, /* x h */ 'A' _ 'r' _ 'r' _ ';', 4, 0x27fa _ 0) -NAMED_CHARACTER_REFERENCE(2093, /* x h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x27f7 _ 0) -NAMED_CHARACTER_REFERENCE(2094, /* x i */ ';', 1, 0x03be _ 0) -NAMED_CHARACTER_REFERENCE(2095, /* x l */ 'A' _ 'r' _ 'r' _ ';', 4, 0x27f8 _ 0) -NAMED_CHARACTER_REFERENCE(2096, /* x l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x27f5 _ 0) -NAMED_CHARACTER_REFERENCE(2097, /* x m */ 'a' _ 'p' _ ';', 3, 0x27fc _ 0) -NAMED_CHARACTER_REFERENCE(2098, /* x n */ 'i' _ 's' _ ';', 3, 0x22fb _ 0) -NAMED_CHARACTER_REFERENCE(2099, /* x o */ 'd' _ 'o' _ 't' _ ';', 4, 0x2a00 _ 0) -NAMED_CHARACTER_REFERENCE(2100, /* x o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd69) -NAMED_CHARACTER_REFERENCE(2101, /* x o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a01 _ 0) -NAMED_CHARACTER_REFERENCE(2102, /* x o */ 't' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2a02 _ 0) -NAMED_CHARACTER_REFERENCE(2103, /* x r */ 'A' _ 'r' _ 'r' _ ';', 4, 0x27f9 _ 0) -NAMED_CHARACTER_REFERENCE(2104, /* x r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x27f6 _ 0) -NAMED_CHARACTER_REFERENCE(2105, /* x s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccd) -NAMED_CHARACTER_REFERENCE(2106, /* x s */ 'q' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a06 _ 0) -NAMED_CHARACTER_REFERENCE(2107, /* x u */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a04 _ 0) -NAMED_CHARACTER_REFERENCE(2108, /* x u */ 't' _ 'r' _ 'i' _ ';', 4, 0x25b3 _ 0) -NAMED_CHARACTER_REFERENCE(2109, /* x v */ 'e' _ 'e' _ ';', 3, 0x22c1 _ 0) -NAMED_CHARACTER_REFERENCE(2110, /* x w */ 'e' _ 'd' _ 'g' _ 'e' _ ';', 5, 0x22c0 _ 0) -NAMED_CHARACTER_REFERENCE(2111, /* y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00fd _ 0) -NAMED_CHARACTER_REFERENCE(2112, /* y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00fd _ 0) -NAMED_CHARACTER_REFERENCE(2113, /* y a */ 'c' _ 'y' _ ';', 3, 0x044f _ 0) -NAMED_CHARACTER_REFERENCE(2114, /* y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0177 _ 0) -NAMED_CHARACTER_REFERENCE(2115, /* y c */ 'y' _ ';', 2, 0x044b _ 0) -NAMED_CHARACTER_REFERENCE(2116, /* y e */ 'n', 1, 0x00a5 _ 0) -NAMED_CHARACTER_REFERENCE(2117, /* y e */ 'n' _ ';', 2, 0x00a5 _ 0) -NAMED_CHARACTER_REFERENCE(2118, /* y f */ 'r' _ ';', 2, 0xd835 _ 0xdd36) -NAMED_CHARACTER_REFERENCE(2119, /* y i */ 'c' _ 'y' _ ';', 3, 0x0457 _ 0) -NAMED_CHARACTER_REFERENCE(2120, /* y o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd6a) -NAMED_CHARACTER_REFERENCE(2121, /* y s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcce) -NAMED_CHARACTER_REFERENCE(2122, /* y u */ 'c' _ 'y' _ ';', 3, 0x044e _ 0) -NAMED_CHARACTER_REFERENCE(2123, /* y u */ 'm' _ 'l', 2, 0x00ff _ 0) -NAMED_CHARACTER_REFERENCE(2124, /* y u */ 'm' _ 'l' _ ';', 3, 0x00ff _ 0) -NAMED_CHARACTER_REFERENCE(2125, /* z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x017a _ 0) -NAMED_CHARACTER_REFERENCE(2126, /* z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x017e _ 0) -NAMED_CHARACTER_REFERENCE(2127, /* z c */ 'y' _ ';', 2, 0x0437 _ 0) -NAMED_CHARACTER_REFERENCE(2128, /* z d */ 'o' _ 't' _ ';', 3, 0x017c _ 0) -NAMED_CHARACTER_REFERENCE(2129, /* z e */ 'e' _ 't' _ 'r' _ 'f' _ ';', 5, 0x2128 _ 0) -NAMED_CHARACTER_REFERENCE(2130, /* z e */ 't' _ 'a' _ ';', 3, 0x03b6 _ 0) -NAMED_CHARACTER_REFERENCE(2131, /* z f */ 'r' _ ';', 2, 0xd835 _ 0xdd37) -NAMED_CHARACTER_REFERENCE(2132, /* z h */ 'c' _ 'y' _ ';', 3, 0x0436 _ 0) -NAMED_CHARACTER_REFERENCE(2133, /* z i */ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21dd _ 0) -NAMED_CHARACTER_REFERENCE(2134, /* z o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd6b) -NAMED_CHARACTER_REFERENCE(2135, /* z s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccf) -NAMED_CHARACTER_REFERENCE(2136, /* z w */ 'j' _ ';', 2, 0x200d _ 0) -NAMED_CHARACTER_REFERENCE(2137, /* z w */ 'n' _ 'j' _ ';', 3, 0x200c _ 0) +NAMED_CHARACTER_REFERENCE(0, /* A E */ 'l' _ 'i' _ 'g', 3, 0, 0x00c6 _ 0) +NAMED_CHARACTER_REFERENCE(1, /* A E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00c6 _ 0) +NAMED_CHARACTER_REFERENCE(2, /* A M */ 'P', 1, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(3, /* A M */ 'P' _ ';', 2, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(4, /* A a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c1 _ 0) +NAMED_CHARACTER_REFERENCE(5, /* A a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00c1 _ 0) +NAMED_CHARACTER_REFERENCE(6, /* A b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x0102 _ 0) +NAMED_CHARACTER_REFERENCE(7, /* A c */ 'i' _ 'r' _ 'c', 3, 0, 0x00c2 _ 0) +NAMED_CHARACTER_REFERENCE(8, /* A c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00c2 _ 0) +NAMED_CHARACTER_REFERENCE(9, /* A c */ 'y' _ ';', 2, 0, 0x0410 _ 0) +NAMED_CHARACTER_REFERENCE(10, /* A f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd04) +NAMED_CHARACTER_REFERENCE(11, /* A g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c0 _ 0) +NAMED_CHARACTER_REFERENCE(12, /* A g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00c0 _ 0) +NAMED_CHARACTER_REFERENCE(13, /* A l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x0391 _ 0) +NAMED_CHARACTER_REFERENCE(14, /* A m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0100 _ 0) +NAMED_CHARACTER_REFERENCE(15, /* A n */ 'd' _ ';', 2, 0, 0x2a53 _ 0) +NAMED_CHARACTER_REFERENCE(16, /* A o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0104 _ 0) +NAMED_CHARACTER_REFERENCE(17, /* A o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd38) +NAMED_CHARACTER_REFERENCE(18, /* A p */ 'p' _ 'l' _ 'y' _ 'F' _ 'u' _ 'n' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, 0, 0x2061 _ 0) +NAMED_CHARACTER_REFERENCE(19, /* A r */ 'i' _ 'n' _ 'g', 3, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(20, /* A r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(21, /* A s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9c) +NAMED_CHARACTER_REFERENCE(22, /* A s */ 's' _ 'i' _ 'g' _ 'n' _ ';', 5, 0, 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(23, /* A t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00c3 _ 0) +NAMED_CHARACTER_REFERENCE(24, /* A t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00c3 _ 0) +NAMED_CHARACTER_REFERENCE(25, /* A u */ 'm' _ 'l', 2, 0, 0x00c4 _ 0) +NAMED_CHARACTER_REFERENCE(26, /* A u */ 'm' _ 'l' _ ';', 3, 0, 0x00c4 _ 0) +NAMED_CHARACTER_REFERENCE(27, /* B a */ 'c' _ 'k' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 8, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(28, /* B a */ 'r' _ 'v' _ ';', 3, 0, 0x2ae7 _ 0) +NAMED_CHARACTER_REFERENCE(29, /* B a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0, 0x2306 _ 0) +NAMED_CHARACTER_REFERENCE(30, /* B c */ 'y' _ ';', 2, 0, 0x0411 _ 0) +NAMED_CHARACTER_REFERENCE(31, /* B e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0, 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(32, /* B e */ 'r' _ 'n' _ 'o' _ 'u' _ 'l' _ 'l' _ 'i' _ 's' _ ';', 9, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(33, /* B e */ 't' _ 'a' _ ';', 3, 0, 0x0392 _ 0) +NAMED_CHARACTER_REFERENCE(34, /* B f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd05) +NAMED_CHARACTER_REFERENCE(35, /* B o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd39) +NAMED_CHARACTER_REFERENCE(36, /* B r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0) +NAMED_CHARACTER_REFERENCE(37, /* B s */ 'c' _ 'r' _ ';', 3, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(38, /* B u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(39, /* C H */ 'c' _ 'y' _ ';', 3, 0, 0x0427 _ 0) +NAMED_CHARACTER_REFERENCE(40, /* C O */ 'P' _ 'Y', 2, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(41, /* C O */ 'P' _ 'Y' _ ';', 3, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(42, /* C a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0106 _ 0) +NAMED_CHARACTER_REFERENCE(43, /* C a */ 'p' _ ';', 2, 0, 0x22d2 _ 0) +NAMED_CHARACTER_REFERENCE(44, /* C a */ 'p' _ 'i' _ 't' _ 'a' _ 'l' _ 'D' _ 'i' _ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 19, 0, 0x2145 _ 0) +NAMED_CHARACTER_REFERENCE(45, /* C a */ 'y' _ 'l' _ 'e' _ 'y' _ 's' _ ';', 6, 0, 0x212d _ 0) +NAMED_CHARACTER_REFERENCE(46, /* C c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010c _ 0) +NAMED_CHARACTER_REFERENCE(47, /* C c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00c7 _ 0) +NAMED_CHARACTER_REFERENCE(48, /* C c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x00c7 _ 0) +NAMED_CHARACTER_REFERENCE(49, /* C c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0108 _ 0) +NAMED_CHARACTER_REFERENCE(50, /* C c */ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 6, 0, 0x2230 _ 0) +NAMED_CHARACTER_REFERENCE(51, /* C d */ 'o' _ 't' _ ';', 3, 0, 0x010a _ 0) +NAMED_CHARACTER_REFERENCE(52, /* C e */ 'd' _ 'i' _ 'l' _ 'l' _ 'a' _ ';', 6, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(53, /* C e */ 'n' _ 't' _ 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(54, /* C f */ 'r' _ ';', 2, 0, 0x212d _ 0) +NAMED_CHARACTER_REFERENCE(55, /* C h */ 'i' _ ';', 2, 0, 0x03a7 _ 0) +NAMED_CHARACTER_REFERENCE(56, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x2299 _ 0) +NAMED_CHARACTER_REFERENCE(57, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 10, 0, 0x2296 _ 0) +NAMED_CHARACTER_REFERENCE(58, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 9, 0, 0x2295 _ 0) +NAMED_CHARACTER_REFERENCE(59, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 10, 0, 0x2297 _ 0) +NAMED_CHARACTER_REFERENCE(60, /* C l */ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 23, 0, 0x2232 _ 0) +NAMED_CHARACTER_REFERENCE(61, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 20, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(62, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 14, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(63, /* C o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x2237 _ 0) +NAMED_CHARACTER_REFERENCE(64, /* C o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0, 0x2a74 _ 0) +NAMED_CHARACTER_REFERENCE(65, /* C o */ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 8, 0, 0x2261 _ 0) +NAMED_CHARACTER_REFERENCE(66, /* C o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0, 0x222f _ 0) +NAMED_CHARACTER_REFERENCE(67, /* C o */ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 14, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(68, /* C o */ 'p' _ 'f' _ ';', 3, 0, 0x2102 _ 0) +NAMED_CHARACTER_REFERENCE(69, /* C o */ 'p' _ 'r' _ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 8, 0, 0x2210 _ 0) +NAMED_CHARACTER_REFERENCE(70, /* C o */ 'u' _ 'n' _ 't' _ 'e' _ 'r' _ 'C' _ 'l' _ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 30, 0, 0x2233 _ 0) +NAMED_CHARACTER_REFERENCE(71, /* C r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2a2f _ 0) +NAMED_CHARACTER_REFERENCE(72, /* C s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9e) +NAMED_CHARACTER_REFERENCE(73, /* C u */ 'p' _ ';', 2, 0, 0x22d3 _ 0) +NAMED_CHARACTER_REFERENCE(74, /* C u */ 'p' _ 'C' _ 'a' _ 'p' _ ';', 5, 0, 0x224d _ 0) +NAMED_CHARACTER_REFERENCE(75, /* D D */ ';', 1, 0, 0x2145 _ 0) +NAMED_CHARACTER_REFERENCE(76, /* D D */ 'o' _ 't' _ 'r' _ 'a' _ 'h' _ 'd' _ ';', 7, 0, 0x2911 _ 0) +NAMED_CHARACTER_REFERENCE(77, /* D J */ 'c' _ 'y' _ ';', 3, 0, 0x0402 _ 0) +NAMED_CHARACTER_REFERENCE(78, /* D S */ 'c' _ 'y' _ ';', 3, 0, 0x0405 _ 0) +NAMED_CHARACTER_REFERENCE(79, /* D Z */ 'c' _ 'y' _ ';', 3, 0, 0x040f _ 0) +NAMED_CHARACTER_REFERENCE(80, /* D a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0, 0x2021 _ 0) +NAMED_CHARACTER_REFERENCE(81, /* D a */ 'r' _ 'r' _ ';', 3, 0, 0x21a1 _ 0) +NAMED_CHARACTER_REFERENCE(82, /* D a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x2ae4 _ 0) +NAMED_CHARACTER_REFERENCE(83, /* D c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010e _ 0) +NAMED_CHARACTER_REFERENCE(84, /* D c */ 'y' _ ';', 2, 0, 0x0414 _ 0) +NAMED_CHARACTER_REFERENCE(85, /* D e */ 'l' _ ';', 2, 0, 0x2207 _ 0) +NAMED_CHARACTER_REFERENCE(86, /* D e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x0394 _ 0) +NAMED_CHARACTER_REFERENCE(87, /* D f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd07) +NAMED_CHARACTER_REFERENCE(88, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 15, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(89, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 't' _ ';', 13, 0, 0x02d9 _ 0) +NAMED_CHARACTER_REFERENCE(90, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 21, 0, 0x02dd _ 0) +NAMED_CHARACTER_REFERENCE(91, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'G' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 15, 0, 0x0060 _ 0) +NAMED_CHARACTER_REFERENCE(92, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 15, 0, 0x02dc _ 0) +NAMED_CHARACTER_REFERENCE(93, /* D i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(94, /* D i */ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 12, 0, 0x2146 _ 0) +NAMED_CHARACTER_REFERENCE(95, /* D o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3b) +NAMED_CHARACTER_REFERENCE(96, /* D o */ 't' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(97, /* D o */ 't' _ 'D' _ 'o' _ 't' _ ';', 5, 0, 0x20dc _ 0) +NAMED_CHARACTER_REFERENCE(98, /* D o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(99, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 20, 0, 0x222f _ 0) +NAMED_CHARACTER_REFERENCE(100, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(101, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(102, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(103, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(104, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 12, 0, 0x2ae4 _ 0) +NAMED_CHARACTER_REFERENCE(105, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(106, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 23, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(107, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(108, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(109, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 13, 0, 0x22a8 _ 0) +NAMED_CHARACTER_REFERENCE(110, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(111, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(112, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 16, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(113, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(114, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0, 0x2913 _ 0) +NAMED_CHARACTER_REFERENCE(115, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x21f5 _ 0) +NAMED_CHARACTER_REFERENCE(116, /* D o */ 'w' _ 'n' _ 'B' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 8, 0, 0x0311 _ 0) +NAMED_CHARACTER_REFERENCE(117, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 18, 0, 0x2950 _ 0) +NAMED_CHARACTER_REFERENCE(118, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x295e _ 0) +NAMED_CHARACTER_REFERENCE(119, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(120, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0, 0x2956 _ 0) +NAMED_CHARACTER_REFERENCE(121, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0, 0x295f _ 0) +NAMED_CHARACTER_REFERENCE(122, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(123, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0, 0x2957 _ 0) +NAMED_CHARACTER_REFERENCE(124, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ ';', 6, 0, 0x22a4 _ 0) +NAMED_CHARACTER_REFERENCE(125, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0, 0x21a7 _ 0) +NAMED_CHARACTER_REFERENCE(126, /* D o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(127, /* D s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9f) +NAMED_CHARACTER_REFERENCE(128, /* D s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0110 _ 0) +NAMED_CHARACTER_REFERENCE(129, /* E N */ 'G' _ ';', 2, 0, 0x014a _ 0) +NAMED_CHARACTER_REFERENCE(130, /* E T */ 'H', 1, 0, 0x00d0 _ 0) +NAMED_CHARACTER_REFERENCE(131, /* E T */ 'H' _ ';', 2, 0, 0x00d0 _ 0) +NAMED_CHARACTER_REFERENCE(132, /* E a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c9 _ 0) +NAMED_CHARACTER_REFERENCE(133, /* E a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00c9 _ 0) +NAMED_CHARACTER_REFERENCE(134, /* E c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x011a _ 0) +NAMED_CHARACTER_REFERENCE(135, /* E c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ca _ 0) +NAMED_CHARACTER_REFERENCE(136, /* E c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ca _ 0) +NAMED_CHARACTER_REFERENCE(137, /* E c */ 'y' _ ';', 2, 0, 0x042d _ 0) +NAMED_CHARACTER_REFERENCE(138, /* E d */ 'o' _ 't' _ ';', 3, 0, 0x0116 _ 0) +NAMED_CHARACTER_REFERENCE(139, /* E f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd08) +NAMED_CHARACTER_REFERENCE(140, /* E g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c8 _ 0) +NAMED_CHARACTER_REFERENCE(141, /* E g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00c8 _ 0) +NAMED_CHARACTER_REFERENCE(142, /* E l */ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 6, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(143, /* E m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0112 _ 0) +NAMED_CHARACTER_REFERENCE(144, /* E m */ 'p' _ 't' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 15, 0, 0x25fb _ 0) +NAMED_CHARACTER_REFERENCE(145, /* E m */ 'p' _ 't' _ 'y' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 19, 0, 0x25ab _ 0) +NAMED_CHARACTER_REFERENCE(146, /* E o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0118 _ 0) +NAMED_CHARACTER_REFERENCE(147, /* E o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3c) +NAMED_CHARACTER_REFERENCE(148, /* E p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x0395 _ 0) +NAMED_CHARACTER_REFERENCE(149, /* E q */ 'u' _ 'a' _ 'l' _ ';', 4, 0, 0x2a75 _ 0) +NAMED_CHARACTER_REFERENCE(150, /* E q */ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(151, /* E q */ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 10, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(152, /* E s */ 'c' _ 'r' _ ';', 3, 0, 0x2130 _ 0) +NAMED_CHARACTER_REFERENCE(153, /* E s */ 'i' _ 'm' _ ';', 3, 0, 0x2a73 _ 0) +NAMED_CHARACTER_REFERENCE(154, /* E t */ 'a' _ ';', 2, 0, 0x0397 _ 0) +NAMED_CHARACTER_REFERENCE(155, /* E u */ 'm' _ 'l', 2, 0, 0x00cb _ 0) +NAMED_CHARACTER_REFERENCE(156, /* E u */ 'm' _ 'l' _ ';', 3, 0, 0x00cb _ 0) +NAMED_CHARACTER_REFERENCE(157, /* E x */ 'i' _ 's' _ 't' _ 's' _ ';', 5, 0, 0x2203 _ 0) +NAMED_CHARACTER_REFERENCE(158, /* E x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'E' _ ';', 11, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(159, /* F c */ 'y' _ ';', 2, 0, 0x0424 _ 0) +NAMED_CHARACTER_REFERENCE(160, /* F f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd09) +NAMED_CHARACTER_REFERENCE(161, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 16, 0, 0x25fc _ 0) +NAMED_CHARACTER_REFERENCE(162, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 20, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(163, /* F o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3d) +NAMED_CHARACTER_REFERENCE(164, /* F o */ 'r' _ 'A' _ 'l' _ 'l' _ ';', 5, 0, 0x2200 _ 0) +NAMED_CHARACTER_REFERENCE(165, /* F o */ 'u' _ 'r' _ 'i' _ 'e' _ 'r' _ 't' _ 'r' _ 'f' _ ';', 9, 0, 0x2131 _ 0) +NAMED_CHARACTER_REFERENCE(166, /* F s */ 'c' _ 'r' _ ';', 3, 0, 0x2131 _ 0) +NAMED_CHARACTER_REFERENCE(167, /* G J */ 'c' _ 'y' _ ';', 3, 0, 0x0403 _ 0) +NAMED_CHARACTER_REFERENCE(168, /* G T */ 0, 0, 1, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(169, /* G T */ ';', 1, 0, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(170, /* G a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x0393 _ 0) +NAMED_CHARACTER_REFERENCE(171, /* G a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0, 0x03dc _ 0) +NAMED_CHARACTER_REFERENCE(172, /* G b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x011e _ 0) +NAMED_CHARACTER_REFERENCE(173, /* G c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0122 _ 0) +NAMED_CHARACTER_REFERENCE(174, /* G c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011c _ 0) +NAMED_CHARACTER_REFERENCE(175, /* G c */ 'y' _ ';', 2, 0, 0x0413 _ 0) +NAMED_CHARACTER_REFERENCE(176, /* G d */ 'o' _ 't' _ ';', 3, 0, 0x0120 _ 0) +NAMED_CHARACTER_REFERENCE(177, /* G f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0a) +NAMED_CHARACTER_REFERENCE(178, /* G g */ ';', 1, 0, 0x22d9 _ 0) +NAMED_CHARACTER_REFERENCE(179, /* G o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3e) +NAMED_CHARACTER_REFERENCE(180, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(181, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'L' _ 'e' _ 's' _ 's' _ ';', 15, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(182, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(183, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0, 0x2aa2 _ 0) +NAMED_CHARACTER_REFERENCE(184, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(185, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(186, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(187, /* G s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca2) +NAMED_CHARACTER_REFERENCE(188, /* G t */ ';', 1, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(189, /* H A */ 'R' _ 'D' _ 'c' _ 'y' _ ';', 5, 0, 0x042a _ 0) +NAMED_CHARACTER_REFERENCE(190, /* H a */ 'c' _ 'e' _ 'k' _ ';', 4, 0, 0x02c7 _ 0) +NAMED_CHARACTER_REFERENCE(191, /* H a */ 't' _ ';', 2, 0, 0x005e _ 0) +NAMED_CHARACTER_REFERENCE(192, /* H c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0124 _ 0) +NAMED_CHARACTER_REFERENCE(193, /* H f */ 'r' _ ';', 2, 0, 0x210c _ 0) +NAMED_CHARACTER_REFERENCE(194, /* H i */ 'l' _ 'b' _ 'e' _ 'r' _ 't' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 11, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(195, /* H o */ 'p' _ 'f' _ ';', 3, 0, 0x210d _ 0) +NAMED_CHARACTER_REFERENCE(196, /* H o */ 'r' _ 'i' _ 'z' _ 'o' _ 'n' _ 't' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 13, 0, 0x2500 _ 0) +NAMED_CHARACTER_REFERENCE(197, /* H s */ 'c' _ 'r' _ ';', 3, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(198, /* H s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0126 _ 0) +NAMED_CHARACTER_REFERENCE(199, /* H u */ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';', 11, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(200, /* H u */ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 8, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(201, /* I E */ 'c' _ 'y' _ ';', 3, 0, 0x0415 _ 0) +NAMED_CHARACTER_REFERENCE(202, /* I J */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0132 _ 0) +NAMED_CHARACTER_REFERENCE(203, /* I O */ 'c' _ 'y' _ ';', 3, 0, 0x0401 _ 0) +NAMED_CHARACTER_REFERENCE(204, /* I a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00cd _ 0) +NAMED_CHARACTER_REFERENCE(205, /* I a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00cd _ 0) +NAMED_CHARACTER_REFERENCE(206, /* I c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ce _ 0) +NAMED_CHARACTER_REFERENCE(207, /* I c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ce _ 0) +NAMED_CHARACTER_REFERENCE(208, /* I c */ 'y' _ ';', 2, 0, 0x0418 _ 0) +NAMED_CHARACTER_REFERENCE(209, /* I d */ 'o' _ 't' _ ';', 3, 0, 0x0130 _ 0) +NAMED_CHARACTER_REFERENCE(210, /* I f */ 'r' _ ';', 2, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(211, /* I g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00cc _ 0) +NAMED_CHARACTER_REFERENCE(212, /* I g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00cc _ 0) +NAMED_CHARACTER_REFERENCE(213, /* I m */ ';', 1, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(214, /* I m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012a _ 0) +NAMED_CHARACTER_REFERENCE(215, /* I m */ 'a' _ 'g' _ 'i' _ 'n' _ 'a' _ 'r' _ 'y' _ 'I' _ ';', 9, 0, 0x2148 _ 0) +NAMED_CHARACTER_REFERENCE(216, /* I m */ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 6, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(217, /* I n */ 't' _ ';', 2, 0, 0x222c _ 0) +NAMED_CHARACTER_REFERENCE(218, /* I n */ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 7, 0, 0x222b _ 0) +NAMED_CHARACTER_REFERENCE(219, /* I n */ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 11, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(220, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 13, 0, 0x2063 _ 0) +NAMED_CHARACTER_REFERENCE(221, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0, 0x2062 _ 0) +NAMED_CHARACTER_REFERENCE(222, /* I o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012e _ 0) +NAMED_CHARACTER_REFERENCE(223, /* I o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd40) +NAMED_CHARACTER_REFERENCE(224, /* I o */ 't' _ 'a' _ ';', 3, 0, 0x0399 _ 0) +NAMED_CHARACTER_REFERENCE(225, /* I s */ 'c' _ 'r' _ ';', 3, 0, 0x2110 _ 0) +NAMED_CHARACTER_REFERENCE(226, /* I t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0128 _ 0) +NAMED_CHARACTER_REFERENCE(227, /* I u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0406 _ 0) +NAMED_CHARACTER_REFERENCE(228, /* I u */ 'm' _ 'l', 2, 0, 0x00cf _ 0) +NAMED_CHARACTER_REFERENCE(229, /* I u */ 'm' _ 'l' _ ';', 3, 0, 0x00cf _ 0) +NAMED_CHARACTER_REFERENCE(230, /* J c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0134 _ 0) +NAMED_CHARACTER_REFERENCE(231, /* J c */ 'y' _ ';', 2, 0, 0x0419 _ 0) +NAMED_CHARACTER_REFERENCE(232, /* J f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0d) +NAMED_CHARACTER_REFERENCE(233, /* J o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd41) +NAMED_CHARACTER_REFERENCE(234, /* J s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca5) +NAMED_CHARACTER_REFERENCE(235, /* J s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0, 0x0408 _ 0) +NAMED_CHARACTER_REFERENCE(236, /* J u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0404 _ 0) +NAMED_CHARACTER_REFERENCE(237, /* K H */ 'c' _ 'y' _ ';', 3, 0, 0x0425 _ 0) +NAMED_CHARACTER_REFERENCE(238, /* K J */ 'c' _ 'y' _ ';', 3, 0, 0x040c _ 0) +NAMED_CHARACTER_REFERENCE(239, /* K a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x039a _ 0) +NAMED_CHARACTER_REFERENCE(240, /* K c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0136 _ 0) +NAMED_CHARACTER_REFERENCE(241, /* K c */ 'y' _ ';', 2, 0, 0x041a _ 0) +NAMED_CHARACTER_REFERENCE(242, /* K f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0e) +NAMED_CHARACTER_REFERENCE(243, /* K o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd42) +NAMED_CHARACTER_REFERENCE(244, /* K s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca6) +NAMED_CHARACTER_REFERENCE(245, /* L J */ 'c' _ 'y' _ ';', 3, 0, 0x0409 _ 0) +NAMED_CHARACTER_REFERENCE(246, /* L T */ 0, 0, 1, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(247, /* L T */ ';', 1, 0, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(248, /* L a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0139 _ 0) +NAMED_CHARACTER_REFERENCE(249, /* L a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0, 0x039b _ 0) +NAMED_CHARACTER_REFERENCE(250, /* L a */ 'n' _ 'g' _ ';', 3, 0, 0x27ea _ 0) +NAMED_CHARACTER_REFERENCE(251, /* L a */ 'p' _ 'l' _ 'a' _ 'c' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 9, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(252, /* L a */ 'r' _ 'r' _ ';', 3, 0, 0x219e _ 0) +NAMED_CHARACTER_REFERENCE(253, /* L c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x013d _ 0) +NAMED_CHARACTER_REFERENCE(254, /* L c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x013b _ 0) +NAMED_CHARACTER_REFERENCE(255, /* L c */ 'y' _ ';', 2, 0, 0x041b _ 0) +NAMED_CHARACTER_REFERENCE(256, /* L e */ 'f' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 15, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(257, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(258, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0, 0x21e4 _ 0) +NAMED_CHARACTER_REFERENCE(259, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(260, /* L e */ 'f' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 10, 0, 0x2308 _ 0) +NAMED_CHARACTER_REFERENCE(261, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0, 0x27e6 _ 0) +NAMED_CHARACTER_REFERENCE(262, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x2961 _ 0) +NAMED_CHARACTER_REFERENCE(263, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(264, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0, 0x2959 _ 0) +NAMED_CHARACTER_REFERENCE(265, /* L e */ 'f' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 8, 0, 0x230a _ 0) +NAMED_CHARACTER_REFERENCE(266, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(267, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x294e _ 0) +NAMED_CHARACTER_REFERENCE(268, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 6, 0, 0x22a3 _ 0) +NAMED_CHARACTER_REFERENCE(269, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0, 0x21a4 _ 0) +NAMED_CHARACTER_REFERENCE(270, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0, 0x295a _ 0) +NAMED_CHARACTER_REFERENCE(271, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 11, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(272, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 14, 0, 0x29cf _ 0) +NAMED_CHARACTER_REFERENCE(273, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(274, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0, 0x2951 _ 0) +NAMED_CHARACTER_REFERENCE(275, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x2960 _ 0) +NAMED_CHARACTER_REFERENCE(276, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 11, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(277, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 14, 0, 0x2958 _ 0) +NAMED_CHARACTER_REFERENCE(278, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 9, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(279, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 12, 0, 0x2952 _ 0) +NAMED_CHARACTER_REFERENCE(280, /* L e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(281, /* L e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(282, /* L e */ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 15, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(283, /* L e */ 's' _ 's' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(284, /* L e */ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 10, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(285, /* L e */ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 7, 0, 0x2aa1 _ 0) +NAMED_CHARACTER_REFERENCE(286, /* L e */ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(287, /* L e */ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 8, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(288, /* L f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0f) +NAMED_CHARACTER_REFERENCE(289, /* L l */ ';', 1, 0, 0x22d8 _ 0) +NAMED_CHARACTER_REFERENCE(290, /* L l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21da _ 0) +NAMED_CHARACTER_REFERENCE(291, /* L m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x013f _ 0) +NAMED_CHARACTER_REFERENCE(292, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(293, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(294, /* L o */ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(295, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(296, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(297, /* L o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(298, /* L o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd43) +NAMED_CHARACTER_REFERENCE(299, /* L o */ 'w' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(300, /* L o */ 'w' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(301, /* L s */ 'c' _ 'r' _ ';', 3, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(302, /* L s */ 'h' _ ';', 2, 0, 0x21b0 _ 0) +NAMED_CHARACTER_REFERENCE(303, /* L s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0141 _ 0) +NAMED_CHARACTER_REFERENCE(304, /* L t */ ';', 1, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(305, /* M a */ 'p' _ ';', 2, 0, 0x2905 _ 0) +NAMED_CHARACTER_REFERENCE(306, /* M c */ 'y' _ ';', 2, 0, 0x041c _ 0) +NAMED_CHARACTER_REFERENCE(307, /* M e */ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 10, 0, 0x205f _ 0) +NAMED_CHARACTER_REFERENCE(308, /* M e */ 'l' _ 'l' _ 'i' _ 'n' _ 't' _ 'r' _ 'f' _ ';', 8, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(309, /* M f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd10) +NAMED_CHARACTER_REFERENCE(310, /* M i */ 'n' _ 'u' _ 's' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(311, /* M o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd44) +NAMED_CHARACTER_REFERENCE(312, /* M s */ 'c' _ 'r' _ ';', 3, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(313, /* M u */ ';', 1, 0, 0x039c _ 0) +NAMED_CHARACTER_REFERENCE(314, /* N J */ 'c' _ 'y' _ ';', 3, 0, 0x040a _ 0) +NAMED_CHARACTER_REFERENCE(315, /* N a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0143 _ 0) +NAMED_CHARACTER_REFERENCE(316, /* N c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0147 _ 0) +NAMED_CHARACTER_REFERENCE(317, /* N c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0145 _ 0) +NAMED_CHARACTER_REFERENCE(318, /* N c */ 'y' _ ';', 2, 0, 0x041d _ 0) +NAMED_CHARACTER_REFERENCE(319, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'M' _ 'e' _ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 18, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(320, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 17, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(321, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 16, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(322, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'V' _ 'e' _ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 20, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(323, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 19, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(324, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(325, /* N e */ 'w' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 6, 0, 0x000a _ 0) +NAMED_CHARACTER_REFERENCE(326, /* N f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd11) +NAMED_CHARACTER_REFERENCE(327, /* N o */ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ ';', 6, 0, 0x2060 _ 0) +NAMED_CHARACTER_REFERENCE(328, /* N o */ 'n' _ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ 'i' _ 'n' _ 'g' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 15, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(329, /* N o */ 'p' _ 'f' _ ';', 3, 0, 0x2115 _ 0) +NAMED_CHARACTER_REFERENCE(330, /* N o */ 't' _ ';', 2, 0, 0x2aec _ 0) +NAMED_CHARACTER_REFERENCE(331, /* N o */ 't' _ 'C' _ 'o' _ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 11, 0, 0x2262 _ 0) +NAMED_CHARACTER_REFERENCE(332, /* N o */ 't' _ 'C' _ 'u' _ 'p' _ 'C' _ 'a' _ 'p' _ ';', 8, 0, 0x226d _ 0) +NAMED_CHARACTER_REFERENCE(333, /* N o */ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 19, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(334, /* N o */ 't' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(335, /* N o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0, 0x2260 _ 0) +NAMED_CHARACTER_REFERENCE(336, /* N o */ 't' _ 'E' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(337, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 9, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(338, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 14, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(339, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0, 0x2279 _ 0) +NAMED_CHARACTER_REFERENCE(340, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 14, 0, 0x2275 _ 0) +NAMED_CHARACTER_REFERENCE(341, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 14, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(342, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(343, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ ';', 6, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(344, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(345, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0, 0x2278 _ 0) +NAMED_CHARACTER_REFERENCE(346, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0, 0x2274 _ 0) +NAMED_CHARACTER_REFERENCE(347, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 10, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(348, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0, 0x22e0 _ 0) +NAMED_CHARACTER_REFERENCE(349, /* N o */ 't' _ 'R' _ 'e' _ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 16, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(350, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 15, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(351, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(352, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0, 0x22e2 _ 0) +NAMED_CHARACTER_REFERENCE(353, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 21, 0, 0x22e3 _ 0) +NAMED_CHARACTER_REFERENCE(354, /* N o */ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(355, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 10, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(356, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0, 0x22e1 _ 0) +NAMED_CHARACTER_REFERENCE(357, /* N o */ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(358, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0, 0x2241 _ 0) +NAMED_CHARACTER_REFERENCE(359, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(360, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x2247 _ 0) +NAMED_CHARACTER_REFERENCE(361, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(362, /* N o */ 't' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 13, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(363, /* N s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca9) +NAMED_CHARACTER_REFERENCE(364, /* N t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d1 _ 0) +NAMED_CHARACTER_REFERENCE(365, /* N t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00d1 _ 0) +NAMED_CHARACTER_REFERENCE(366, /* N u */ ';', 1, 0, 0x039d _ 0) +NAMED_CHARACTER_REFERENCE(367, /* O E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0152 _ 0) +NAMED_CHARACTER_REFERENCE(368, /* O a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00d3 _ 0) +NAMED_CHARACTER_REFERENCE(369, /* O a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00d3 _ 0) +NAMED_CHARACTER_REFERENCE(370, /* O c */ 'i' _ 'r' _ 'c', 3, 0, 0x00d4 _ 0) +NAMED_CHARACTER_REFERENCE(371, /* O c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00d4 _ 0) +NAMED_CHARACTER_REFERENCE(372, /* O c */ 'y' _ ';', 2, 0, 0x041e _ 0) +NAMED_CHARACTER_REFERENCE(373, /* O d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0150 _ 0) +NAMED_CHARACTER_REFERENCE(374, /* O f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd12) +NAMED_CHARACTER_REFERENCE(375, /* O g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d2 _ 0) +NAMED_CHARACTER_REFERENCE(376, /* O g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00d2 _ 0) +NAMED_CHARACTER_REFERENCE(377, /* O m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014c _ 0) +NAMED_CHARACTER_REFERENCE(378, /* O m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03a9 _ 0) +NAMED_CHARACTER_REFERENCE(379, /* O m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0, 0x039f _ 0) +NAMED_CHARACTER_REFERENCE(380, /* O o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd46) +NAMED_CHARACTER_REFERENCE(381, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 19, 0, 0x201c _ 0) +NAMED_CHARACTER_REFERENCE(382, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 13, 0, 0x2018 _ 0) +NAMED_CHARACTER_REFERENCE(383, /* O r */ ';', 1, 0, 0x2a54 _ 0) +NAMED_CHARACTER_REFERENCE(384, /* O s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaa) +NAMED_CHARACTER_REFERENCE(385, /* O s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00d8 _ 0) +NAMED_CHARACTER_REFERENCE(386, /* O s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x00d8 _ 0) +NAMED_CHARACTER_REFERENCE(387, /* O t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d5 _ 0) +NAMED_CHARACTER_REFERENCE(388, /* O t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00d5 _ 0) +NAMED_CHARACTER_REFERENCE(389, /* O t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x2a37 _ 0) +NAMED_CHARACTER_REFERENCE(390, /* O u */ 'm' _ 'l', 2, 0, 0x00d6 _ 0) +NAMED_CHARACTER_REFERENCE(391, /* O u */ 'm' _ 'l' _ ';', 3, 0, 0x00d6 _ 0) +NAMED_CHARACTER_REFERENCE(392, /* O v */ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 6, 0, 0x203e _ 0) +NAMED_CHARACTER_REFERENCE(393, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x23de _ 0) +NAMED_CHARACTER_REFERENCE(394, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 10, 0, 0x23b4 _ 0) +NAMED_CHARACTER_REFERENCE(395, /* O v */ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 14, 0, 0x23dc _ 0) +NAMED_CHARACTER_REFERENCE(396, /* P a */ 'r' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 7, 0, 0x2202 _ 0) +NAMED_CHARACTER_REFERENCE(397, /* P c */ 'y' _ ';', 2, 0, 0x041f _ 0) +NAMED_CHARACTER_REFERENCE(398, /* P f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd13) +NAMED_CHARACTER_REFERENCE(399, /* P h */ 'i' _ ';', 2, 0, 0x03a6 _ 0) +NAMED_CHARACTER_REFERENCE(400, /* P i */ ';', 1, 0, 0x03a0 _ 0) +NAMED_CHARACTER_REFERENCE(401, /* P l */ 'u' _ 's' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 8, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(402, /* P o */ 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ 'p' _ 'l' _ 'a' _ 'n' _ 'e' _ ';', 12, 0, 0x210c _ 0) +NAMED_CHARACTER_REFERENCE(403, /* P o */ 'p' _ 'f' _ ';', 3, 0, 0x2119 _ 0) +NAMED_CHARACTER_REFERENCE(404, /* P r */ ';', 1, 0, 0x2abb _ 0) +NAMED_CHARACTER_REFERENCE(405, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 7, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(406, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(407, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(408, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(409, /* P r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2033 _ 0) +NAMED_CHARACTER_REFERENCE(410, /* P r */ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 6, 0, 0x220f _ 0) +NAMED_CHARACTER_REFERENCE(411, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 9, 0, 0x2237 _ 0) +NAMED_CHARACTER_REFERENCE(412, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ ';', 11, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(413, /* P s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcab) +NAMED_CHARACTER_REFERENCE(414, /* P s */ 'i' _ ';', 2, 0, 0x03a8 _ 0) +NAMED_CHARACTER_REFERENCE(415, /* Q U */ 'O' _ 'T', 2, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(416, /* Q U */ 'O' _ 'T' _ ';', 3, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(417, /* Q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd14) +NAMED_CHARACTER_REFERENCE(418, /* Q o */ 'p' _ 'f' _ ';', 3, 0, 0x211a _ 0) +NAMED_CHARACTER_REFERENCE(419, /* Q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcac) +NAMED_CHARACTER_REFERENCE(420, /* R B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2910 _ 0) +NAMED_CHARACTER_REFERENCE(421, /* R E */ 'G', 1, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(422, /* R E */ 'G' _ ';', 2, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(423, /* R a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0154 _ 0) +NAMED_CHARACTER_REFERENCE(424, /* R a */ 'n' _ 'g' _ ';', 3, 0, 0x27eb _ 0) +NAMED_CHARACTER_REFERENCE(425, /* R a */ 'r' _ 'r' _ ';', 3, 0, 0x21a0 _ 0) +NAMED_CHARACTER_REFERENCE(426, /* R a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, 0x2916 _ 0) +NAMED_CHARACTER_REFERENCE(427, /* R c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0158 _ 0) +NAMED_CHARACTER_REFERENCE(428, /* R c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0156 _ 0) +NAMED_CHARACTER_REFERENCE(429, /* R c */ 'y' _ ';', 2, 0, 0x0420 _ 0) +NAMED_CHARACTER_REFERENCE(430, /* R e */ ';', 1, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(431, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 13, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(432, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 17, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(433, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'U' _ 'p' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 19, 0, 0x296f _ 0) +NAMED_CHARACTER_REFERENCE(434, /* R f */ 'r' _ ';', 2, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(435, /* R h */ 'o' _ ';', 2, 0, 0x03a1 _ 0) +NAMED_CHARACTER_REFERENCE(436, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(437, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(438, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 12, 0, 0x21e5 _ 0) +NAMED_CHARACTER_REFERENCE(439, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(440, /* R i */ 'g' _ 'h' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 11, 0, 0x2309 _ 0) +NAMED_CHARACTER_REFERENCE(441, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 17, 0, 0x27e7 _ 0) +NAMED_CHARACTER_REFERENCE(442, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0, 0x295d _ 0) +NAMED_CHARACTER_REFERENCE(443, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(444, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0, 0x2955 _ 0) +NAMED_CHARACTER_REFERENCE(445, /* R i */ 'g' _ 'h' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 9, 0, 0x230b _ 0) +NAMED_CHARACTER_REFERENCE(446, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 7, 0, 0x22a2 _ 0) +NAMED_CHARACTER_REFERENCE(447, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(448, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0, 0x295b _ 0) +NAMED_CHARACTER_REFERENCE(449, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(450, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 15, 0, 0x29d0 _ 0) +NAMED_CHARACTER_REFERENCE(451, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(452, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x294f _ 0) +NAMED_CHARACTER_REFERENCE(453, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0, 0x295c _ 0) +NAMED_CHARACTER_REFERENCE(454, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(455, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 15, 0, 0x2954 _ 0) +NAMED_CHARACTER_REFERENCE(456, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 10, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(457, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 13, 0, 0x2953 _ 0) +NAMED_CHARACTER_REFERENCE(458, /* R i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(459, /* R o */ 'p' _ 'f' _ ';', 3, 0, 0x211d _ 0) +NAMED_CHARACTER_REFERENCE(460, /* R o */ 'u' _ 'n' _ 'd' _ 'I' _ 'm' _ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 11, 0, 0x2970 _ 0) +NAMED_CHARACTER_REFERENCE(461, /* R r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x21db _ 0) +NAMED_CHARACTER_REFERENCE(462, /* R s */ 'c' _ 'r' _ ';', 3, 0, 0x211b _ 0) +NAMED_CHARACTER_REFERENCE(463, /* R s */ 'h' _ ';', 2, 0, 0x21b1 _ 0) +NAMED_CHARACTER_REFERENCE(464, /* R u */ 'l' _ 'e' _ 'D' _ 'e' _ 'l' _ 'a' _ 'y' _ 'e' _ 'd' _ ';', 10, 0, 0x29f4 _ 0) +NAMED_CHARACTER_REFERENCE(465, /* S H */ 'C' _ 'H' _ 'c' _ 'y' _ ';', 5, 0, 0x0429 _ 0) +NAMED_CHARACTER_REFERENCE(466, /* S H */ 'c' _ 'y' _ ';', 3, 0, 0x0428 _ 0) +NAMED_CHARACTER_REFERENCE(467, /* S O */ 'F' _ 'T' _ 'c' _ 'y' _ ';', 5, 0, 0x042c _ 0) +NAMED_CHARACTER_REFERENCE(468, /* S a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x015a _ 0) +NAMED_CHARACTER_REFERENCE(469, /* S c */ ';', 1, 0, 0x2abc _ 0) +NAMED_CHARACTER_REFERENCE(470, /* S c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0160 _ 0) +NAMED_CHARACTER_REFERENCE(471, /* S c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x015e _ 0) +NAMED_CHARACTER_REFERENCE(472, /* S c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015c _ 0) +NAMED_CHARACTER_REFERENCE(473, /* S c */ 'y' _ ';', 2, 0, 0x0421 _ 0) +NAMED_CHARACTER_REFERENCE(474, /* S f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd16) +NAMED_CHARACTER_REFERENCE(475, /* S h */ 'o' _ 'r' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(476, /* S h */ 'o' _ 'r' _ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(477, /* S h */ 'o' _ 'r' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(478, /* S h */ 'o' _ 'r' _ 't' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(479, /* S i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03a3 _ 0) +NAMED_CHARACTER_REFERENCE(480, /* S m */ 'a' _ 'l' _ 'l' _ 'C' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ ';', 10, 0, 0x2218 _ 0) +NAMED_CHARACTER_REFERENCE(481, /* S o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4a) +NAMED_CHARACTER_REFERENCE(482, /* S q */ 'r' _ 't' _ ';', 3, 0, 0x221a _ 0) +NAMED_CHARACTER_REFERENCE(483, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(484, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'I' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 17, 0, 0x2293 _ 0) +NAMED_CHARACTER_REFERENCE(485, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 11, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(486, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(487, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 13, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(488, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 18, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(489, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'U' _ 'n' _ 'i' _ 'o' _ 'n' _ ';', 10, 0, 0x2294 _ 0) +NAMED_CHARACTER_REFERENCE(490, /* S s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcae) +NAMED_CHARACTER_REFERENCE(491, /* S t */ 'a' _ 'r' _ ';', 3, 0, 0x22c6 _ 0) +NAMED_CHARACTER_REFERENCE(492, /* S u */ 'b' _ ';', 2, 0, 0x22d0 _ 0) +NAMED_CHARACTER_REFERENCE(493, /* S u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x22d0 _ 0) +NAMED_CHARACTER_REFERENCE(494, /* S u */ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 10, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(495, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 7, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(496, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(497, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(498, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(499, /* S u */ 'c' _ 'h' _ 'T' _ 'h' _ 'a' _ 't' _ ';', 7, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(500, /* S u */ 'm' _ ';', 2, 0, 0x2211 _ 0) +NAMED_CHARACTER_REFERENCE(501, /* S u */ 'p' _ ';', 2, 0, 0x22d1 _ 0) +NAMED_CHARACTER_REFERENCE(502, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(503, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(504, /* S u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x22d1 _ 0) +NAMED_CHARACTER_REFERENCE(505, /* T H */ 'O' _ 'R' _ 'N', 3, 0, 0x00de _ 0) +NAMED_CHARACTER_REFERENCE(506, /* T H */ 'O' _ 'R' _ 'N' _ ';', 4, 0, 0x00de _ 0) +NAMED_CHARACTER_REFERENCE(507, /* T R */ 'A' _ 'D' _ 'E' _ ';', 4, 0, 0x2122 _ 0) +NAMED_CHARACTER_REFERENCE(508, /* T S */ 'H' _ 'c' _ 'y' _ ';', 4, 0, 0x040b _ 0) +NAMED_CHARACTER_REFERENCE(509, /* T S */ 'c' _ 'y' _ ';', 3, 0, 0x0426 _ 0) +NAMED_CHARACTER_REFERENCE(510, /* T a */ 'b' _ ';', 2, 0, 0x0009 _ 0) +NAMED_CHARACTER_REFERENCE(511, /* T a */ 'u' _ ';', 2, 0, 0x03a4 _ 0) +NAMED_CHARACTER_REFERENCE(512, /* T c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0164 _ 0) +NAMED_CHARACTER_REFERENCE(513, /* T c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0162 _ 0) +NAMED_CHARACTER_REFERENCE(514, /* T c */ 'y' _ ';', 2, 0, 0x0422 _ 0) +NAMED_CHARACTER_REFERENCE(515, /* T f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd17) +NAMED_CHARACTER_REFERENCE(516, /* T h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(517, /* T h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x0398 _ 0) +NAMED_CHARACTER_REFERENCE(518, /* T h */ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x2009 _ 0) +NAMED_CHARACTER_REFERENCE(519, /* T i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(520, /* T i */ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 9, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(521, /* T i */ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0, 0x2245 _ 0) +NAMED_CHARACTER_REFERENCE(522, /* T i */ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(523, /* T o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4b) +NAMED_CHARACTER_REFERENCE(524, /* T r */ 'i' _ 'p' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x20db _ 0) +NAMED_CHARACTER_REFERENCE(525, /* T s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaf) +NAMED_CHARACTER_REFERENCE(526, /* T s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0166 _ 0) +NAMED_CHARACTER_REFERENCE(527, /* U a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00da _ 0) +NAMED_CHARACTER_REFERENCE(528, /* U a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00da _ 0) +NAMED_CHARACTER_REFERENCE(529, /* U a */ 'r' _ 'r' _ ';', 3, 0, 0x219f _ 0) +NAMED_CHARACTER_REFERENCE(530, /* U a */ 'r' _ 'r' _ 'o' _ 'c' _ 'i' _ 'r' _ ';', 7, 0, 0x2949 _ 0) +NAMED_CHARACTER_REFERENCE(531, /* U b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x040e _ 0) +NAMED_CHARACTER_REFERENCE(532, /* U b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x016c _ 0) +NAMED_CHARACTER_REFERENCE(533, /* U c */ 'i' _ 'r' _ 'c', 3, 0, 0x00db _ 0) +NAMED_CHARACTER_REFERENCE(534, /* U c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00db _ 0) +NAMED_CHARACTER_REFERENCE(535, /* U c */ 'y' _ ';', 2, 0, 0x0423 _ 0) +NAMED_CHARACTER_REFERENCE(536, /* U d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0170 _ 0) +NAMED_CHARACTER_REFERENCE(537, /* U f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd18) +NAMED_CHARACTER_REFERENCE(538, /* U g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d9 _ 0) +NAMED_CHARACTER_REFERENCE(539, /* U g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00d9 _ 0) +NAMED_CHARACTER_REFERENCE(540, /* U m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016a _ 0) +NAMED_CHARACTER_REFERENCE(541, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 7, 0, 0x005f _ 0) +NAMED_CHARACTER_REFERENCE(542, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 9, 0, 0x23df _ 0) +NAMED_CHARACTER_REFERENCE(543, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 11, 0, 0x23b5 _ 0) +NAMED_CHARACTER_REFERENCE(544, /* U n */ 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 15, 0, 0x23dd _ 0) +NAMED_CHARACTER_REFERENCE(545, /* U n */ 'i' _ 'o' _ 'n' _ ';', 4, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(546, /* U n */ 'i' _ 'o' _ 'n' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x228e _ 0) +NAMED_CHARACTER_REFERENCE(547, /* U o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0172 _ 0) +NAMED_CHARACTER_REFERENCE(548, /* U o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4c) +NAMED_CHARACTER_REFERENCE(549, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(550, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 9, 0, 0x2912 _ 0) +NAMED_CHARACTER_REFERENCE(551, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x21c5 _ 0) +NAMED_CHARACTER_REFERENCE(552, /* U p */ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(553, /* U p */ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 12, 0, 0x296e _ 0) +NAMED_CHARACTER_REFERENCE(554, /* U p */ 'T' _ 'e' _ 'e' _ ';', 4, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(555, /* U p */ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21a5 _ 0) +NAMED_CHARACTER_REFERENCE(556, /* U p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(557, /* U p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(558, /* U p */ 'p' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(559, /* U p */ 'p' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(560, /* U p */ 's' _ 'i' _ ';', 3, 0, 0x03d2 _ 0) +NAMED_CHARACTER_REFERENCE(561, /* U p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x03a5 _ 0) +NAMED_CHARACTER_REFERENCE(562, /* U r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016e _ 0) +NAMED_CHARACTER_REFERENCE(563, /* U s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb0) +NAMED_CHARACTER_REFERENCE(564, /* U t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0168 _ 0) +NAMED_CHARACTER_REFERENCE(565, /* U u */ 'm' _ 'l', 2, 0, 0x00dc _ 0) +NAMED_CHARACTER_REFERENCE(566, /* U u */ 'm' _ 'l' _ ';', 3, 0, 0x00dc _ 0) +NAMED_CHARACTER_REFERENCE(567, /* V D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22ab _ 0) +NAMED_CHARACTER_REFERENCE(568, /* V b */ 'a' _ 'r' _ ';', 3, 0, 0x2aeb _ 0) +NAMED_CHARACTER_REFERENCE(569, /* V c */ 'y' _ ';', 2, 0, 0x0412 _ 0) +NAMED_CHARACTER_REFERENCE(570, /* V d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a9 _ 0) +NAMED_CHARACTER_REFERENCE(571, /* V d */ 'a' _ 's' _ 'h' _ 'l' _ ';', 5, 0, 0x2ae6 _ 0) +NAMED_CHARACTER_REFERENCE(572, /* V e */ 'e' _ ';', 2, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(573, /* V e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x2016 _ 0) +NAMED_CHARACTER_REFERENCE(574, /* V e */ 'r' _ 't' _ ';', 3, 0, 0x2016 _ 0) +NAMED_CHARACTER_REFERENCE(575, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 10, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(576, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 11, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(577, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'S' _ 'e' _ 'p' _ 'a' _ 'r' _ 'a' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x2758 _ 0) +NAMED_CHARACTER_REFERENCE(578, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(579, /* V e */ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 12, 0, 0x200a _ 0) +NAMED_CHARACTER_REFERENCE(580, /* V f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd19) +NAMED_CHARACTER_REFERENCE(581, /* V o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4d) +NAMED_CHARACTER_REFERENCE(582, /* V s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb1) +NAMED_CHARACTER_REFERENCE(583, /* V v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22aa _ 0) +NAMED_CHARACTER_REFERENCE(584, /* W c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0174 _ 0) +NAMED_CHARACTER_REFERENCE(585, /* W e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(586, /* W f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1a) +NAMED_CHARACTER_REFERENCE(587, /* W o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4e) +NAMED_CHARACTER_REFERENCE(588, /* W s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb2) +NAMED_CHARACTER_REFERENCE(589, /* X f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1b) +NAMED_CHARACTER_REFERENCE(590, /* X i */ ';', 1, 0, 0x039e _ 0) +NAMED_CHARACTER_REFERENCE(591, /* X o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4f) +NAMED_CHARACTER_REFERENCE(592, /* X s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb3) +NAMED_CHARACTER_REFERENCE(593, /* Y A */ 'c' _ 'y' _ ';', 3, 0, 0x042f _ 0) +NAMED_CHARACTER_REFERENCE(594, /* Y I */ 'c' _ 'y' _ ';', 3, 0, 0x0407 _ 0) +NAMED_CHARACTER_REFERENCE(595, /* Y U */ 'c' _ 'y' _ ';', 3, 0, 0x042e _ 0) +NAMED_CHARACTER_REFERENCE(596, /* Y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00dd _ 0) +NAMED_CHARACTER_REFERENCE(597, /* Y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00dd _ 0) +NAMED_CHARACTER_REFERENCE(598, /* Y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0176 _ 0) +NAMED_CHARACTER_REFERENCE(599, /* Y c */ 'y' _ ';', 2, 0, 0x042b _ 0) +NAMED_CHARACTER_REFERENCE(600, /* Y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1c) +NAMED_CHARACTER_REFERENCE(601, /* Y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd50) +NAMED_CHARACTER_REFERENCE(602, /* Y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb4) +NAMED_CHARACTER_REFERENCE(603, /* Y u */ 'm' _ 'l' _ ';', 3, 0, 0x0178 _ 0) +NAMED_CHARACTER_REFERENCE(604, /* Z H */ 'c' _ 'y' _ ';', 3, 0, 0x0416 _ 0) +NAMED_CHARACTER_REFERENCE(605, /* Z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0179 _ 0) +NAMED_CHARACTER_REFERENCE(606, /* Z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x017d _ 0) +NAMED_CHARACTER_REFERENCE(607, /* Z c */ 'y' _ ';', 2, 0, 0x0417 _ 0) +NAMED_CHARACTER_REFERENCE(608, /* Z d */ 'o' _ 't' _ ';', 3, 0, 0x017b _ 0) +NAMED_CHARACTER_REFERENCE(609, /* Z e */ 'r' _ 'o' _ 'W' _ 'i' _ 'd' _ 't' _ 'h' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 13, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(610, /* Z e */ 't' _ 'a' _ ';', 3, 0, 0x0396 _ 0) +NAMED_CHARACTER_REFERENCE(611, /* Z f */ 'r' _ ';', 2, 0, 0x2128 _ 0) +NAMED_CHARACTER_REFERENCE(612, /* Z o */ 'p' _ 'f' _ ';', 3, 0, 0x2124 _ 0) +NAMED_CHARACTER_REFERENCE(613, /* Z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb5) +NAMED_CHARACTER_REFERENCE(614, /* a a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e1 _ 0) +NAMED_CHARACTER_REFERENCE(615, /* a a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00e1 _ 0) +NAMED_CHARACTER_REFERENCE(616, /* a b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x0103 _ 0) +NAMED_CHARACTER_REFERENCE(617, /* a c */ ';', 1, 0, 0x223e _ 0) +NAMED_CHARACTER_REFERENCE(618, /* a c */ 'd' _ ';', 2, 0, 0x223f _ 0) +NAMED_CHARACTER_REFERENCE(619, /* a c */ 'i' _ 'r' _ 'c', 3, 0, 0x00e2 _ 0) +NAMED_CHARACTER_REFERENCE(620, /* a c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00e2 _ 0) +NAMED_CHARACTER_REFERENCE(621, /* a c */ 'u' _ 't' _ 'e', 3, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(622, /* a c */ 'u' _ 't' _ 'e' _ ';', 4, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(623, /* a c */ 'y' _ ';', 2, 0, 0x0430 _ 0) +NAMED_CHARACTER_REFERENCE(624, /* a e */ 'l' _ 'i' _ 'g', 3, 0, 0x00e6 _ 0) +NAMED_CHARACTER_REFERENCE(625, /* a e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00e6 _ 0) +NAMED_CHARACTER_REFERENCE(626, /* a f */ ';', 1, 0, 0x2061 _ 0) +NAMED_CHARACTER_REFERENCE(627, /* a f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1e) +NAMED_CHARACTER_REFERENCE(628, /* a g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e0 _ 0) +NAMED_CHARACTER_REFERENCE(629, /* a g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00e0 _ 0) +NAMED_CHARACTER_REFERENCE(630, /* a l */ 'e' _ 'f' _ 's' _ 'y' _ 'm' _ ';', 6, 0, 0x2135 _ 0) +NAMED_CHARACTER_REFERENCE(631, /* a l */ 'e' _ 'p' _ 'h' _ ';', 4, 0, 0x2135 _ 0) +NAMED_CHARACTER_REFERENCE(632, /* a l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x03b1 _ 0) +NAMED_CHARACTER_REFERENCE(633, /* a m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0101 _ 0) +NAMED_CHARACTER_REFERENCE(634, /* a m */ 'a' _ 'l' _ 'g' _ ';', 4, 0, 0x2a3f _ 0) +NAMED_CHARACTER_REFERENCE(635, /* a m */ 'p', 1, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(636, /* a m */ 'p' _ ';', 2, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(637, /* a n */ 'd' _ ';', 2, 0, 0x2227 _ 0) +NAMED_CHARACTER_REFERENCE(638, /* a n */ 'd' _ 'a' _ 'n' _ 'd' _ ';', 5, 0, 0x2a55 _ 0) +NAMED_CHARACTER_REFERENCE(639, /* a n */ 'd' _ 'd' _ ';', 3, 0, 0x2a5c _ 0) +NAMED_CHARACTER_REFERENCE(640, /* a n */ 'd' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 7, 0, 0x2a58 _ 0) +NAMED_CHARACTER_REFERENCE(641, /* a n */ 'd' _ 'v' _ ';', 3, 0, 0x2a5a _ 0) +NAMED_CHARACTER_REFERENCE(642, /* a n */ 'g' _ ';', 2, 0, 0x2220 _ 0) +NAMED_CHARACTER_REFERENCE(643, /* a n */ 'g' _ 'e' _ ';', 3, 0, 0x29a4 _ 0) +NAMED_CHARACTER_REFERENCE(644, /* a n */ 'g' _ 'l' _ 'e' _ ';', 4, 0, 0x2220 _ 0) +NAMED_CHARACTER_REFERENCE(645, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ ';', 5, 0, 0x2221 _ 0) +NAMED_CHARACTER_REFERENCE(646, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'a' _ ';', 7, 0, 0x29a8 _ 0) +NAMED_CHARACTER_REFERENCE(647, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'b' _ ';', 7, 0, 0x29a9 _ 0) +NAMED_CHARACTER_REFERENCE(648, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'c' _ ';', 7, 0, 0x29aa _ 0) +NAMED_CHARACTER_REFERENCE(649, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'd' _ ';', 7, 0, 0x29ab _ 0) +NAMED_CHARACTER_REFERENCE(650, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'e' _ ';', 7, 0, 0x29ac _ 0) +NAMED_CHARACTER_REFERENCE(651, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'f' _ ';', 7, 0, 0x29ad _ 0) +NAMED_CHARACTER_REFERENCE(652, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'g' _ ';', 7, 0, 0x29ae _ 0) +NAMED_CHARACTER_REFERENCE(653, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'h' _ ';', 7, 0, 0x29af _ 0) +NAMED_CHARACTER_REFERENCE(654, /* a n */ 'g' _ 'r' _ 't' _ ';', 4, 0, 0x221f _ 0) +NAMED_CHARACTER_REFERENCE(655, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 6, 0, 0x22be _ 0) +NAMED_CHARACTER_REFERENCE(656, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 7, 0, 0x299d _ 0) +NAMED_CHARACTER_REFERENCE(657, /* a n */ 'g' _ 's' _ 'p' _ 'h' _ ';', 5, 0, 0x2222 _ 0) +NAMED_CHARACTER_REFERENCE(658, /* a n */ 'g' _ 's' _ 't' _ ';', 4, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(659, /* a n */ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x237c _ 0) +NAMED_CHARACTER_REFERENCE(660, /* a o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0105 _ 0) +NAMED_CHARACTER_REFERENCE(661, /* a o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd52) +NAMED_CHARACTER_REFERENCE(662, /* a p */ ';', 1, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(663, /* a p */ 'E' _ ';', 2, 0, 0x2a70 _ 0) +NAMED_CHARACTER_REFERENCE(664, /* a p */ 'a' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, 0x2a6f _ 0) +NAMED_CHARACTER_REFERENCE(665, /* a p */ 'e' _ ';', 2, 0, 0x224a _ 0) +NAMED_CHARACTER_REFERENCE(666, /* a p */ 'i' _ 'd' _ ';', 3, 0, 0x224b _ 0) +NAMED_CHARACTER_REFERENCE(667, /* a p */ 'o' _ 's' _ ';', 3, 0, 0x0027 _ 0) +NAMED_CHARACTER_REFERENCE(668, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ ';', 5, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(669, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ 'e' _ 'q' _ ';', 7, 0, 0x224a _ 0) +NAMED_CHARACTER_REFERENCE(670, /* a r */ 'i' _ 'n' _ 'g', 3, 0, 0x00e5 _ 0) +NAMED_CHARACTER_REFERENCE(671, /* a r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00e5 _ 0) +NAMED_CHARACTER_REFERENCE(672, /* a s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb6) +NAMED_CHARACTER_REFERENCE(673, /* a s */ 't' _ ';', 2, 0, 0x002a _ 0) +NAMED_CHARACTER_REFERENCE(674, /* a s */ 'y' _ 'm' _ 'p' _ ';', 4, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(675, /* a s */ 'y' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 6, 0, 0x224d _ 0) +NAMED_CHARACTER_REFERENCE(676, /* a t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00e3 _ 0) +NAMED_CHARACTER_REFERENCE(677, /* a t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00e3 _ 0) +NAMED_CHARACTER_REFERENCE(678, /* a u */ 'm' _ 'l', 2, 0, 0x00e4 _ 0) +NAMED_CHARACTER_REFERENCE(679, /* a u */ 'm' _ 'l' _ ';', 3, 0, 0x00e4 _ 0) +NAMED_CHARACTER_REFERENCE(680, /* a w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2233 _ 0) +NAMED_CHARACTER_REFERENCE(681, /* a w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2a11 _ 0) +NAMED_CHARACTER_REFERENCE(682, /* b N */ 'o' _ 't' _ ';', 3, 0, 0x2aed _ 0) +NAMED_CHARACTER_REFERENCE(683, /* b a */ 'c' _ 'k' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 7, 0, 0x224c _ 0) +NAMED_CHARACTER_REFERENCE(684, /* b a */ 'c' _ 'k' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 10, 0, 0x03f6 _ 0) +NAMED_CHARACTER_REFERENCE(685, /* b a */ 'c' _ 'k' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 8, 0, 0x2035 _ 0) +NAMED_CHARACTER_REFERENCE(686, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x223d _ 0) +NAMED_CHARACTER_REFERENCE(687, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 8, 0, 0x22cd _ 0) +NAMED_CHARACTER_REFERENCE(688, /* b a */ 'r' _ 'v' _ 'e' _ 'e' _ ';', 5, 0, 0x22bd _ 0) +NAMED_CHARACTER_REFERENCE(689, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0, 0x2305 _ 0) +NAMED_CHARACTER_REFERENCE(690, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0, 0x2305 _ 0) +NAMED_CHARACTER_REFERENCE(691, /* b b */ 'r' _ 'k' _ ';', 3, 0, 0x23b5 _ 0) +NAMED_CHARACTER_REFERENCE(692, /* b b */ 'r' _ 'k' _ 't' _ 'b' _ 'r' _ 'k' _ ';', 7, 0, 0x23b6 _ 0) +NAMED_CHARACTER_REFERENCE(693, /* b c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x224c _ 0) +NAMED_CHARACTER_REFERENCE(694, /* b c */ 'y' _ ';', 2, 0, 0x0431 _ 0) +NAMED_CHARACTER_REFERENCE(695, /* b d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201e _ 0) +NAMED_CHARACTER_REFERENCE(696, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ ';', 5, 0, 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(697, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0, 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(698, /* b e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, 0x29b0 _ 0) +NAMED_CHARACTER_REFERENCE(699, /* b e */ 'p' _ 's' _ 'i' _ ';', 4, 0, 0x03f6 _ 0) +NAMED_CHARACTER_REFERENCE(700, /* b e */ 'r' _ 'n' _ 'o' _ 'u' _ ';', 5, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(701, /* b e */ 't' _ 'a' _ ';', 3, 0, 0x03b2 _ 0) +NAMED_CHARACTER_REFERENCE(702, /* b e */ 't' _ 'h' _ ';', 3, 0, 0x2136 _ 0) +NAMED_CHARACTER_REFERENCE(703, /* b e */ 't' _ 'w' _ 'e' _ 'e' _ 'n' _ ';', 6, 0, 0x226c _ 0) +NAMED_CHARACTER_REFERENCE(704, /* b f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1f) +NAMED_CHARACTER_REFERENCE(705, /* b i */ 'g' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(706, /* b i */ 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0, 0x25ef _ 0) +NAMED_CHARACTER_REFERENCE(707, /* b i */ 'g' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(708, /* b i */ 'g' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2a00 _ 0) +NAMED_CHARACTER_REFERENCE(709, /* b i */ 'g' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0, 0x2a01 _ 0) +NAMED_CHARACTER_REFERENCE(710, /* b i */ 'g' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0, 0x2a02 _ 0) +NAMED_CHARACTER_REFERENCE(711, /* b i */ 'g' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, 0, 0x2a06 _ 0) +NAMED_CHARACTER_REFERENCE(712, /* b i */ 'g' _ 's' _ 't' _ 'a' _ 'r' _ ';', 6, 0, 0x2605 _ 0) +NAMED_CHARACTER_REFERENCE(713, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0, 0x25bd _ 0) +NAMED_CHARACTER_REFERENCE(714, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'u' _ 'p' _ ';', 12, 0, 0x25b3 _ 0) +NAMED_CHARACTER_REFERENCE(715, /* b i */ 'g' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0, 0x2a04 _ 0) +NAMED_CHARACTER_REFERENCE(716, /* b i */ 'g' _ 'v' _ 'e' _ 'e' _ ';', 5, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(717, /* b i */ 'g' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(718, /* b k */ 'a' _ 'r' _ 'o' _ 'w' _ ';', 5, 0, 0x290d _ 0) +NAMED_CHARACTER_REFERENCE(719, /* b l */ 'a' _ 'c' _ 'k' _ 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 11, 0, 0x29eb _ 0) +NAMED_CHARACTER_REFERENCE(720, /* b l */ 'a' _ 'c' _ 'k' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(721, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0, 0x25b4 _ 0) +NAMED_CHARACTER_REFERENCE(722, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 16, 0, 0x25be _ 0) +NAMED_CHARACTER_REFERENCE(723, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0, 0x25c2 _ 0) +NAMED_CHARACTER_REFERENCE(724, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0, 0x25b8 _ 0) +NAMED_CHARACTER_REFERENCE(725, /* b l */ 'a' _ 'n' _ 'k' _ ';', 4, 0, 0x2423 _ 0) +NAMED_CHARACTER_REFERENCE(726, /* b l */ 'k' _ '1' _ '2' _ ';', 4, 0, 0x2592 _ 0) +NAMED_CHARACTER_REFERENCE(727, /* b l */ 'k' _ '1' _ '4' _ ';', 4, 0, 0x2591 _ 0) +NAMED_CHARACTER_REFERENCE(728, /* b l */ 'k' _ '3' _ '4' _ ';', 4, 0, 0x2593 _ 0) +NAMED_CHARACTER_REFERENCE(729, /* b l */ 'o' _ 'c' _ 'k' _ ';', 4, 0, 0x2588 _ 0) +NAMED_CHARACTER_REFERENCE(730, /* b n */ 'o' _ 't' _ ';', 3, 0, 0x2310 _ 0) +NAMED_CHARACTER_REFERENCE(731, /* b o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd53) +NAMED_CHARACTER_REFERENCE(732, /* b o */ 't' _ ';', 2, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(733, /* b o */ 't' _ 't' _ 'o' _ 'm' _ ';', 5, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(734, /* b o */ 'w' _ 't' _ 'i' _ 'e' _ ';', 5, 0, 0x22c8 _ 0) +NAMED_CHARACTER_REFERENCE(735, /* b o */ 'x' _ 'D' _ 'L' _ ';', 4, 0, 0x2557 _ 0) +NAMED_CHARACTER_REFERENCE(736, /* b o */ 'x' _ 'D' _ 'R' _ ';', 4, 0, 0x2554 _ 0) +NAMED_CHARACTER_REFERENCE(737, /* b o */ 'x' _ 'D' _ 'l' _ ';', 4, 0, 0x2556 _ 0) +NAMED_CHARACTER_REFERENCE(738, /* b o */ 'x' _ 'D' _ 'r' _ ';', 4, 0, 0x2553 _ 0) +NAMED_CHARACTER_REFERENCE(739, /* b o */ 'x' _ 'H' _ ';', 3, 0, 0x2550 _ 0) +NAMED_CHARACTER_REFERENCE(740, /* b o */ 'x' _ 'H' _ 'D' _ ';', 4, 0, 0x2566 _ 0) +NAMED_CHARACTER_REFERENCE(741, /* b o */ 'x' _ 'H' _ 'U' _ ';', 4, 0, 0x2569 _ 0) +NAMED_CHARACTER_REFERENCE(742, /* b o */ 'x' _ 'H' _ 'd' _ ';', 4, 0, 0x2564 _ 0) +NAMED_CHARACTER_REFERENCE(743, /* b o */ 'x' _ 'H' _ 'u' _ ';', 4, 0, 0x2567 _ 0) +NAMED_CHARACTER_REFERENCE(744, /* b o */ 'x' _ 'U' _ 'L' _ ';', 4, 0, 0x255d _ 0) +NAMED_CHARACTER_REFERENCE(745, /* b o */ 'x' _ 'U' _ 'R' _ ';', 4, 0, 0x255a _ 0) +NAMED_CHARACTER_REFERENCE(746, /* b o */ 'x' _ 'U' _ 'l' _ ';', 4, 0, 0x255c _ 0) +NAMED_CHARACTER_REFERENCE(747, /* b o */ 'x' _ 'U' _ 'r' _ ';', 4, 0, 0x2559 _ 0) +NAMED_CHARACTER_REFERENCE(748, /* b o */ 'x' _ 'V' _ ';', 3, 0, 0x2551 _ 0) +NAMED_CHARACTER_REFERENCE(749, /* b o */ 'x' _ 'V' _ 'H' _ ';', 4, 0, 0x256c _ 0) +NAMED_CHARACTER_REFERENCE(750, /* b o */ 'x' _ 'V' _ 'L' _ ';', 4, 0, 0x2563 _ 0) +NAMED_CHARACTER_REFERENCE(751, /* b o */ 'x' _ 'V' _ 'R' _ ';', 4, 0, 0x2560 _ 0) +NAMED_CHARACTER_REFERENCE(752, /* b o */ 'x' _ 'V' _ 'h' _ ';', 4, 0, 0x256b _ 0) +NAMED_CHARACTER_REFERENCE(753, /* b o */ 'x' _ 'V' _ 'l' _ ';', 4, 0, 0x2562 _ 0) +NAMED_CHARACTER_REFERENCE(754, /* b o */ 'x' _ 'V' _ 'r' _ ';', 4, 0, 0x255f _ 0) +NAMED_CHARACTER_REFERENCE(755, /* b o */ 'x' _ 'b' _ 'o' _ 'x' _ ';', 5, 0, 0x29c9 _ 0) +NAMED_CHARACTER_REFERENCE(756, /* b o */ 'x' _ 'd' _ 'L' _ ';', 4, 0, 0x2555 _ 0) +NAMED_CHARACTER_REFERENCE(757, /* b o */ 'x' _ 'd' _ 'R' _ ';', 4, 0, 0x2552 _ 0) +NAMED_CHARACTER_REFERENCE(758, /* b o */ 'x' _ 'd' _ 'l' _ ';', 4, 0, 0x2510 _ 0) +NAMED_CHARACTER_REFERENCE(759, /* b o */ 'x' _ 'd' _ 'r' _ ';', 4, 0, 0x250c _ 0) +NAMED_CHARACTER_REFERENCE(760, /* b o */ 'x' _ 'h' _ ';', 3, 0, 0x2500 _ 0) +NAMED_CHARACTER_REFERENCE(761, /* b o */ 'x' _ 'h' _ 'D' _ ';', 4, 0, 0x2565 _ 0) +NAMED_CHARACTER_REFERENCE(762, /* b o */ 'x' _ 'h' _ 'U' _ ';', 4, 0, 0x2568 _ 0) +NAMED_CHARACTER_REFERENCE(763, /* b o */ 'x' _ 'h' _ 'd' _ ';', 4, 0, 0x252c _ 0) +NAMED_CHARACTER_REFERENCE(764, /* b o */ 'x' _ 'h' _ 'u' _ ';', 4, 0, 0x2534 _ 0) +NAMED_CHARACTER_REFERENCE(765, /* b o */ 'x' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x229f _ 0) +NAMED_CHARACTER_REFERENCE(766, /* b o */ 'x' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x229e _ 0) +NAMED_CHARACTER_REFERENCE(767, /* b o */ 'x' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0, 0x22a0 _ 0) +NAMED_CHARACTER_REFERENCE(768, /* b o */ 'x' _ 'u' _ 'L' _ ';', 4, 0, 0x255b _ 0) +NAMED_CHARACTER_REFERENCE(769, /* b o */ 'x' _ 'u' _ 'R' _ ';', 4, 0, 0x2558 _ 0) +NAMED_CHARACTER_REFERENCE(770, /* b o */ 'x' _ 'u' _ 'l' _ ';', 4, 0, 0x2518 _ 0) +NAMED_CHARACTER_REFERENCE(771, /* b o */ 'x' _ 'u' _ 'r' _ ';', 4, 0, 0x2514 _ 0) +NAMED_CHARACTER_REFERENCE(772, /* b o */ 'x' _ 'v' _ ';', 3, 0, 0x2502 _ 0) +NAMED_CHARACTER_REFERENCE(773, /* b o */ 'x' _ 'v' _ 'H' _ ';', 4, 0, 0x256a _ 0) +NAMED_CHARACTER_REFERENCE(774, /* b o */ 'x' _ 'v' _ 'L' _ ';', 4, 0, 0x2561 _ 0) +NAMED_CHARACTER_REFERENCE(775, /* b o */ 'x' _ 'v' _ 'R' _ ';', 4, 0, 0x255e _ 0) +NAMED_CHARACTER_REFERENCE(776, /* b o */ 'x' _ 'v' _ 'h' _ ';', 4, 0, 0x253c _ 0) +NAMED_CHARACTER_REFERENCE(777, /* b o */ 'x' _ 'v' _ 'l' _ ';', 4, 0, 0x2524 _ 0) +NAMED_CHARACTER_REFERENCE(778, /* b o */ 'x' _ 'v' _ 'r' _ ';', 4, 0, 0x251c _ 0) +NAMED_CHARACTER_REFERENCE(779, /* b p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2035 _ 0) +NAMED_CHARACTER_REFERENCE(780, /* b r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0) +NAMED_CHARACTER_REFERENCE(781, /* b r */ 'v' _ 'b' _ 'a' _ 'r', 4, 0, 0x00a6 _ 0) +NAMED_CHARACTER_REFERENCE(782, /* b r */ 'v' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x00a6 _ 0) +NAMED_CHARACTER_REFERENCE(783, /* b s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb7) +NAMED_CHARACTER_REFERENCE(784, /* b s */ 'e' _ 'm' _ 'i' _ ';', 4, 0, 0x204f _ 0) +NAMED_CHARACTER_REFERENCE(785, /* b s */ 'i' _ 'm' _ ';', 3, 0, 0x223d _ 0) +NAMED_CHARACTER_REFERENCE(786, /* b s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x22cd _ 0) +NAMED_CHARACTER_REFERENCE(787, /* b s */ 'o' _ 'l' _ ';', 3, 0, 0x005c _ 0) +NAMED_CHARACTER_REFERENCE(788, /* b s */ 'o' _ 'l' _ 'b' _ ';', 4, 0, 0x29c5 _ 0) +NAMED_CHARACTER_REFERENCE(789, /* b s */ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 7, 0, 0x27c8 _ 0) +NAMED_CHARACTER_REFERENCE(790, /* b u */ 'l' _ 'l' _ ';', 3, 0, 0x2022 _ 0) +NAMED_CHARACTER_REFERENCE(791, /* b u */ 'l' _ 'l' _ 'e' _ 't' _ ';', 5, 0, 0x2022 _ 0) +NAMED_CHARACTER_REFERENCE(792, /* b u */ 'm' _ 'p' _ ';', 3, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(793, /* b u */ 'm' _ 'p' _ 'E' _ ';', 4, 0, 0x2aae _ 0) +NAMED_CHARACTER_REFERENCE(794, /* b u */ 'm' _ 'p' _ 'e' _ ';', 4, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(795, /* b u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(796, /* c a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0107 _ 0) +NAMED_CHARACTER_REFERENCE(797, /* c a */ 'p' _ ';', 2, 0, 0x2229 _ 0) +NAMED_CHARACTER_REFERENCE(798, /* c a */ 'p' _ 'a' _ 'n' _ 'd' _ ';', 5, 0, 0x2a44 _ 0) +NAMED_CHARACTER_REFERENCE(799, /* c a */ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 7, 0, 0x2a49 _ 0) +NAMED_CHARACTER_REFERENCE(800, /* c a */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, 0x2a4b _ 0) +NAMED_CHARACTER_REFERENCE(801, /* c a */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x2a47 _ 0) +NAMED_CHARACTER_REFERENCE(802, /* c a */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a40 _ 0) +NAMED_CHARACTER_REFERENCE(803, /* c a */ 'r' _ 'e' _ 't' _ ';', 4, 0, 0x2041 _ 0) +NAMED_CHARACTER_REFERENCE(804, /* c a */ 'r' _ 'o' _ 'n' _ ';', 4, 0, 0x02c7 _ 0) +NAMED_CHARACTER_REFERENCE(805, /* c c */ 'a' _ 'p' _ 's' _ ';', 4, 0, 0x2a4d _ 0) +NAMED_CHARACTER_REFERENCE(806, /* c c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010d _ 0) +NAMED_CHARACTER_REFERENCE(807, /* c c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00e7 _ 0) +NAMED_CHARACTER_REFERENCE(808, /* c c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x00e7 _ 0) +NAMED_CHARACTER_REFERENCE(809, /* c c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0109 _ 0) +NAMED_CHARACTER_REFERENCE(810, /* c c */ 'u' _ 'p' _ 's' _ ';', 4, 0, 0x2a4c _ 0) +NAMED_CHARACTER_REFERENCE(811, /* c c */ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 6, 0, 0x2a50 _ 0) +NAMED_CHARACTER_REFERENCE(812, /* c d */ 'o' _ 't' _ ';', 3, 0, 0x010b _ 0) +NAMED_CHARACTER_REFERENCE(813, /* c e */ 'd' _ 'i' _ 'l', 3, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(814, /* c e */ 'd' _ 'i' _ 'l' _ ';', 4, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(815, /* c e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, 0x29b2 _ 0) +NAMED_CHARACTER_REFERENCE(816, /* c e */ 'n' _ 't', 2, 0, 0x00a2 _ 0) +NAMED_CHARACTER_REFERENCE(817, /* c e */ 'n' _ 't' _ ';', 3, 0, 0x00a2 _ 0) +NAMED_CHARACTER_REFERENCE(818, /* c e */ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(819, /* c f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd20) +NAMED_CHARACTER_REFERENCE(820, /* c h */ 'c' _ 'y' _ ';', 3, 0, 0x0447 _ 0) +NAMED_CHARACTER_REFERENCE(821, /* c h */ 'e' _ 'c' _ 'k' _ ';', 4, 0, 0x2713 _ 0) +NAMED_CHARACTER_REFERENCE(822, /* c h */ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 8, 0, 0x2713 _ 0) +NAMED_CHARACTER_REFERENCE(823, /* c h */ 'i' _ ';', 2, 0, 0x03c7 _ 0) +NAMED_CHARACTER_REFERENCE(824, /* c i */ 'r' _ ';', 2, 0, 0x25cb _ 0) +NAMED_CHARACTER_REFERENCE(825, /* c i */ 'r' _ 'E' _ ';', 3, 0, 0x29c3 _ 0) +NAMED_CHARACTER_REFERENCE(826, /* c i */ 'r' _ 'c' _ ';', 3, 0, 0x02c6 _ 0) +NAMED_CHARACTER_REFERENCE(827, /* c i */ 'r' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, 0x2257 _ 0) +NAMED_CHARACTER_REFERENCE(828, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0, 0x21ba _ 0) +NAMED_CHARACTER_REFERENCE(829, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0, 0x21bb _ 0) +NAMED_CHARACTER_REFERENCE(830, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 7, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(831, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 7, 0, 0x24c8 _ 0) +NAMED_CHARACTER_REFERENCE(832, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 9, 0, 0x229b _ 0) +NAMED_CHARACTER_REFERENCE(833, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 10, 0, 0x229a _ 0) +NAMED_CHARACTER_REFERENCE(834, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 10, 0, 0x229d _ 0) +NAMED_CHARACTER_REFERENCE(835, /* c i */ 'r' _ 'e' _ ';', 3, 0, 0x2257 _ 0) +NAMED_CHARACTER_REFERENCE(836, /* c i */ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a10 _ 0) +NAMED_CHARACTER_REFERENCE(837, /* c i */ 'r' _ 'm' _ 'i' _ 'd' _ ';', 5, 0, 0x2aef _ 0) +NAMED_CHARACTER_REFERENCE(838, /* c i */ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, 0x29c2 _ 0) +NAMED_CHARACTER_REFERENCE(839, /* c l */ 'u' _ 'b' _ 's' _ ';', 4, 0, 0x2663 _ 0) +NAMED_CHARACTER_REFERENCE(840, /* c l */ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 7, 0, 0x2663 _ 0) +NAMED_CHARACTER_REFERENCE(841, /* c o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x003a _ 0) +NAMED_CHARACTER_REFERENCE(842, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0, 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(843, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 6, 0, 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(844, /* c o */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x002c _ 0) +NAMED_CHARACTER_REFERENCE(845, /* c o */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0, 0x0040 _ 0) +NAMED_CHARACTER_REFERENCE(846, /* c o */ 'm' _ 'p' _ ';', 3, 0, 0x2201 _ 0) +NAMED_CHARACTER_REFERENCE(847, /* c o */ 'm' _ 'p' _ 'f' _ 'n' _ ';', 5, 0, 0x2218 _ 0) +NAMED_CHARACTER_REFERENCE(848, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0, 0x2201 _ 0) +NAMED_CHARACTER_REFERENCE(849, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 8, 0, 0x2102 _ 0) +NAMED_CHARACTER_REFERENCE(850, /* c o */ 'n' _ 'g' _ ';', 3, 0, 0x2245 _ 0) +NAMED_CHARACTER_REFERENCE(851, /* c o */ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2a6d _ 0) +NAMED_CHARACTER_REFERENCE(852, /* c o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(853, /* c o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd54) +NAMED_CHARACTER_REFERENCE(854, /* c o */ 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0, 0x2210 _ 0) +NAMED_CHARACTER_REFERENCE(855, /* c o */ 'p' _ 'y', 2, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(856, /* c o */ 'p' _ 'y' _ ';', 3, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(857, /* c o */ 'p' _ 'y' _ 's' _ 'r' _ ';', 5, 0, 0x2117 _ 0) +NAMED_CHARACTER_REFERENCE(858, /* c r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21b5 _ 0) +NAMED_CHARACTER_REFERENCE(859, /* c r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2717 _ 0) +NAMED_CHARACTER_REFERENCE(860, /* c s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb8) +NAMED_CHARACTER_REFERENCE(861, /* c s */ 'u' _ 'b' _ ';', 3, 0, 0x2acf _ 0) +NAMED_CHARACTER_REFERENCE(862, /* c s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2ad1 _ 0) +NAMED_CHARACTER_REFERENCE(863, /* c s */ 'u' _ 'p' _ ';', 3, 0, 0x2ad0 _ 0) +NAMED_CHARACTER_REFERENCE(864, /* c s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2ad2 _ 0) +NAMED_CHARACTER_REFERENCE(865, /* c t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22ef _ 0) +NAMED_CHARACTER_REFERENCE(866, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 6, 0, 0x2938 _ 0) +NAMED_CHARACTER_REFERENCE(867, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 6, 0, 0x2935 _ 0) +NAMED_CHARACTER_REFERENCE(868, /* c u */ 'e' _ 'p' _ 'r' _ ';', 4, 0, 0x22de _ 0) +NAMED_CHARACTER_REFERENCE(869, /* c u */ 'e' _ 's' _ 'c' _ ';', 4, 0, 0x22df _ 0) +NAMED_CHARACTER_REFERENCE(870, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x21b6 _ 0) +NAMED_CHARACTER_REFERENCE(871, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 6, 0, 0x293d _ 0) +NAMED_CHARACTER_REFERENCE(872, /* c u */ 'p' _ ';', 2, 0, 0x222a _ 0) +NAMED_CHARACTER_REFERENCE(873, /* c u */ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 7, 0, 0x2a48 _ 0) +NAMED_CHARACTER_REFERENCE(874, /* c u */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, 0x2a46 _ 0) +NAMED_CHARACTER_REFERENCE(875, /* c u */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x2a4a _ 0) +NAMED_CHARACTER_REFERENCE(876, /* c u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x228d _ 0) +NAMED_CHARACTER_REFERENCE(877, /* c u */ 'p' _ 'o' _ 'r' _ ';', 4, 0, 0x2a45 _ 0) +NAMED_CHARACTER_REFERENCE(878, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x21b7 _ 0) +NAMED_CHARACTER_REFERENCE(879, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 6, 0, 0x293c _ 0) +NAMED_CHARACTER_REFERENCE(880, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 10, 0, 0x22de _ 0) +NAMED_CHARACTER_REFERENCE(881, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 10, 0, 0x22df _ 0) +NAMED_CHARACTER_REFERENCE(882, /* c u */ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 7, 0, 0x22ce _ 0) +NAMED_CHARACTER_REFERENCE(883, /* c u */ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 9, 0, 0x22cf _ 0) +NAMED_CHARACTER_REFERENCE(884, /* c u */ 'r' _ 'r' _ 'e' _ 'n', 4, 0, 0x00a4 _ 0) +NAMED_CHARACTER_REFERENCE(885, /* c u */ 'r' _ 'r' _ 'e' _ 'n' _ ';', 5, 0, 0x00a4 _ 0) +NAMED_CHARACTER_REFERENCE(886, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 13, 0, 0x21b6 _ 0) +NAMED_CHARACTER_REFERENCE(887, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 14, 0, 0x21b7 _ 0) +NAMED_CHARACTER_REFERENCE(888, /* c u */ 'v' _ 'e' _ 'e' _ ';', 4, 0, 0x22ce _ 0) +NAMED_CHARACTER_REFERENCE(889, /* c u */ 'w' _ 'e' _ 'd' _ ';', 4, 0, 0x22cf _ 0) +NAMED_CHARACTER_REFERENCE(890, /* c w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2232 _ 0) +NAMED_CHARACTER_REFERENCE(891, /* c w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2231 _ 0) +NAMED_CHARACTER_REFERENCE(892, /* c y */ 'l' _ 'c' _ 't' _ 'y' _ ';', 5, 0, 0x232d _ 0) +NAMED_CHARACTER_REFERENCE(893, /* d A */ 'r' _ 'r' _ ';', 3, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(894, /* d H */ 'a' _ 'r' _ ';', 3, 0, 0x2965 _ 0) +NAMED_CHARACTER_REFERENCE(895, /* d a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0, 0x2020 _ 0) +NAMED_CHARACTER_REFERENCE(896, /* d a */ 'l' _ 'e' _ 't' _ 'h' _ ';', 5, 0, 0x2138 _ 0) +NAMED_CHARACTER_REFERENCE(897, /* d a */ 'r' _ 'r' _ ';', 3, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(898, /* d a */ 's' _ 'h' _ ';', 3, 0, 0x2010 _ 0) +NAMED_CHARACTER_REFERENCE(899, /* d a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x22a3 _ 0) +NAMED_CHARACTER_REFERENCE(900, /* d b */ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x290f _ 0) +NAMED_CHARACTER_REFERENCE(901, /* d b */ 'l' _ 'a' _ 'c' _ ';', 4, 0, 0x02dd _ 0) +NAMED_CHARACTER_REFERENCE(902, /* d c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010f _ 0) +NAMED_CHARACTER_REFERENCE(903, /* d c */ 'y' _ ';', 2, 0, 0x0434 _ 0) +NAMED_CHARACTER_REFERENCE(904, /* d d */ ';', 1, 0, 0x2146 _ 0) +NAMED_CHARACTER_REFERENCE(905, /* d d */ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 6, 0, 0x2021 _ 0) +NAMED_CHARACTER_REFERENCE(906, /* d d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ca _ 0) +NAMED_CHARACTER_REFERENCE(907, /* d d */ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 6, 0, 0x2a77 _ 0) +NAMED_CHARACTER_REFERENCE(908, /* d e */ 'g', 1, 0, 0x00b0 _ 0) +NAMED_CHARACTER_REFERENCE(909, /* d e */ 'g' _ ';', 2, 0, 0x00b0 _ 0) +NAMED_CHARACTER_REFERENCE(910, /* d e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x03b4 _ 0) +NAMED_CHARACTER_REFERENCE(911, /* d e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, 0x29b1 _ 0) +NAMED_CHARACTER_REFERENCE(912, /* d f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297f _ 0) +NAMED_CHARACTER_REFERENCE(913, /* d f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd21) +NAMED_CHARACTER_REFERENCE(914, /* d h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(915, /* d h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(916, /* d i */ 'a' _ 'm' _ ';', 3, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(917, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(918, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0, 0x2666 _ 0) +NAMED_CHARACTER_REFERENCE(919, /* d i */ 'a' _ 'm' _ 's' _ ';', 4, 0, 0x2666 _ 0) +NAMED_CHARACTER_REFERENCE(920, /* d i */ 'e' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(921, /* d i */ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0, 0x03dd _ 0) +NAMED_CHARACTER_REFERENCE(922, /* d i */ 's' _ 'i' _ 'n' _ ';', 4, 0, 0x22f2 _ 0) +NAMED_CHARACTER_REFERENCE(923, /* d i */ 'v' _ ';', 2, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(924, /* d i */ 'v' _ 'i' _ 'd' _ 'e', 4, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(925, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ ';', 5, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(926, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 12, 0, 0x22c7 _ 0) +NAMED_CHARACTER_REFERENCE(927, /* d i */ 'v' _ 'o' _ 'n' _ 'x' _ ';', 5, 0, 0x22c7 _ 0) +NAMED_CHARACTER_REFERENCE(928, /* d j */ 'c' _ 'y' _ ';', 3, 0, 0x0452 _ 0) +NAMED_CHARACTER_REFERENCE(929, /* d l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231e _ 0) +NAMED_CHARACTER_REFERENCE(930, /* d l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230d _ 0) +NAMED_CHARACTER_REFERENCE(931, /* d o */ 'l' _ 'l' _ 'a' _ 'r' _ ';', 5, 0, 0x0024 _ 0) +NAMED_CHARACTER_REFERENCE(932, /* d o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd55) +NAMED_CHARACTER_REFERENCE(933, /* d o */ 't' _ ';', 2, 0, 0x02d9 _ 0) +NAMED_CHARACTER_REFERENCE(934, /* d o */ 't' _ 'e' _ 'q' _ ';', 4, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(935, /* d o */ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 7, 0, 0x2251 _ 0) +NAMED_CHARACTER_REFERENCE(936, /* d o */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x2238 _ 0) +NAMED_CHARACTER_REFERENCE(937, /* d o */ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2214 _ 0) +NAMED_CHARACTER_REFERENCE(938, /* d o */ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 8, 0, 0x22a1 _ 0) +NAMED_CHARACTER_REFERENCE(939, /* d o */ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 13, 0, 0x2306 _ 0) +NAMED_CHARACTER_REFERENCE(940, /* d o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(941, /* d o */ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0, 0x21ca _ 0) +NAMED_CHARACTER_REFERENCE(942, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(943, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(944, /* d r */ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0, 0x2910 _ 0) +NAMED_CHARACTER_REFERENCE(945, /* d r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231f _ 0) +NAMED_CHARACTER_REFERENCE(946, /* d r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230c _ 0) +NAMED_CHARACTER_REFERENCE(947, /* d s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb9) +NAMED_CHARACTER_REFERENCE(948, /* d s */ 'c' _ 'y' _ ';', 3, 0, 0x0455 _ 0) +NAMED_CHARACTER_REFERENCE(949, /* d s */ 'o' _ 'l' _ ';', 3, 0, 0x29f6 _ 0) +NAMED_CHARACTER_REFERENCE(950, /* d s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0111 _ 0) +NAMED_CHARACTER_REFERENCE(951, /* d t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f1 _ 0) +NAMED_CHARACTER_REFERENCE(952, /* d t */ 'r' _ 'i' _ ';', 3, 0, 0x25bf _ 0) +NAMED_CHARACTER_REFERENCE(953, /* d t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25be _ 0) +NAMED_CHARACTER_REFERENCE(954, /* d u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21f5 _ 0) +NAMED_CHARACTER_REFERENCE(955, /* d u */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296f _ 0) +NAMED_CHARACTER_REFERENCE(956, /* d w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0, 0x29a6 _ 0) +NAMED_CHARACTER_REFERENCE(957, /* d z */ 'c' _ 'y' _ ';', 3, 0, 0x045f _ 0) +NAMED_CHARACTER_REFERENCE(958, /* d z */ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0, 0x27ff _ 0) +NAMED_CHARACTER_REFERENCE(959, /* e D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2a77 _ 0) +NAMED_CHARACTER_REFERENCE(960, /* e D */ 'o' _ 't' _ ';', 3, 0, 0x2251 _ 0) +NAMED_CHARACTER_REFERENCE(961, /* e a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e9 _ 0) +NAMED_CHARACTER_REFERENCE(962, /* e a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00e9 _ 0) +NAMED_CHARACTER_REFERENCE(963, /* e a */ 's' _ 't' _ 'e' _ 'r' _ ';', 5, 0, 0x2a6e _ 0) +NAMED_CHARACTER_REFERENCE(964, /* e c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x011b _ 0) +NAMED_CHARACTER_REFERENCE(965, /* e c */ 'i' _ 'r' _ ';', 3, 0, 0x2256 _ 0) +NAMED_CHARACTER_REFERENCE(966, /* e c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ea _ 0) +NAMED_CHARACTER_REFERENCE(967, /* e c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ea _ 0) +NAMED_CHARACTER_REFERENCE(968, /* e c */ 'o' _ 'l' _ 'o' _ 'n' _ ';', 5, 0, 0x2255 _ 0) +NAMED_CHARACTER_REFERENCE(969, /* e c */ 'y' _ ';', 2, 0, 0x044d _ 0) +NAMED_CHARACTER_REFERENCE(970, /* e d */ 'o' _ 't' _ ';', 3, 0, 0x0117 _ 0) +NAMED_CHARACTER_REFERENCE(971, /* e e */ ';', 1, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(972, /* e f */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2252 _ 0) +NAMED_CHARACTER_REFERENCE(973, /* e f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd22) +NAMED_CHARACTER_REFERENCE(974, /* e g */ ';', 1, 0, 0x2a9a _ 0) +NAMED_CHARACTER_REFERENCE(975, /* e g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e8 _ 0) +NAMED_CHARACTER_REFERENCE(976, /* e g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00e8 _ 0) +NAMED_CHARACTER_REFERENCE(977, /* e g */ 's' _ ';', 2, 0, 0x2a96 _ 0) +NAMED_CHARACTER_REFERENCE(978, /* e g */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a98 _ 0) +NAMED_CHARACTER_REFERENCE(979, /* e l */ ';', 1, 0, 0x2a99 _ 0) +NAMED_CHARACTER_REFERENCE(980, /* e l */ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 7, 0, 0x23e7 _ 0) +NAMED_CHARACTER_REFERENCE(981, /* e l */ 'l' _ ';', 2, 0, 0x2113 _ 0) +NAMED_CHARACTER_REFERENCE(982, /* e l */ 's' _ ';', 2, 0, 0x2a95 _ 0) +NAMED_CHARACTER_REFERENCE(983, /* e l */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a97 _ 0) +NAMED_CHARACTER_REFERENCE(984, /* e m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0113 _ 0) +NAMED_CHARACTER_REFERENCE(985, /* e m */ 'p' _ 't' _ 'y' _ ';', 4, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(986, /* e m */ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(987, /* e m */ 'p' _ 't' _ 'y' _ 'v' _ ';', 5, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(988, /* e m */ 's' _ 'p' _ '1' _ '3' _ ';', 5, 0, 0x2004 _ 0) +NAMED_CHARACTER_REFERENCE(989, /* e m */ 's' _ 'p' _ '1' _ '4' _ ';', 5, 0, 0x2005 _ 0) +NAMED_CHARACTER_REFERENCE(990, /* e m */ 's' _ 'p' _ ';', 3, 0, 0x2003 _ 0) +NAMED_CHARACTER_REFERENCE(991, /* e n */ 'g' _ ';', 2, 0, 0x014b _ 0) +NAMED_CHARACTER_REFERENCE(992, /* e n */ 's' _ 'p' _ ';', 3, 0, 0x2002 _ 0) +NAMED_CHARACTER_REFERENCE(993, /* e o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0119 _ 0) +NAMED_CHARACTER_REFERENCE(994, /* e o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd56) +NAMED_CHARACTER_REFERENCE(995, /* e p */ 'a' _ 'r' _ ';', 3, 0, 0x22d5 _ 0) +NAMED_CHARACTER_REFERENCE(996, /* e p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0, 0x29e3 _ 0) +NAMED_CHARACTER_REFERENCE(997, /* e p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2a71 _ 0) +NAMED_CHARACTER_REFERENCE(998, /* e p */ 's' _ 'i' _ ';', 3, 0, 0x03b5 _ 0) +NAMED_CHARACTER_REFERENCE(999, /* e p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x03b5 _ 0) +NAMED_CHARACTER_REFERENCE(1000, /* e p */ 's' _ 'i' _ 'v' _ ';', 4, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(1001, /* e q */ 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0, 0x2256 _ 0) +NAMED_CHARACTER_REFERENCE(1002, /* e q */ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x2255 _ 0) +NAMED_CHARACTER_REFERENCE(1003, /* e q */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(1004, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 9, 0, 0x2a96 _ 0) +NAMED_CHARACTER_REFERENCE(1005, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0, 0x2a95 _ 0) +NAMED_CHARACTER_REFERENCE(1006, /* e q */ 'u' _ 'a' _ 'l' _ 's' _ ';', 5, 0, 0x003d _ 0) +NAMED_CHARACTER_REFERENCE(1007, /* e q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0, 0x225f _ 0) +NAMED_CHARACTER_REFERENCE(1008, /* e q */ 'u' _ 'i' _ 'v' _ ';', 4, 0, 0x2261 _ 0) +NAMED_CHARACTER_REFERENCE(1009, /* e q */ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 6, 0, 0x2a78 _ 0) +NAMED_CHARACTER_REFERENCE(1010, /* e q */ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0, 0x29e5 _ 0) +NAMED_CHARACTER_REFERENCE(1011, /* e r */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2253 _ 0) +NAMED_CHARACTER_REFERENCE(1012, /* e r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2971 _ 0) +NAMED_CHARACTER_REFERENCE(1013, /* e s */ 'c' _ 'r' _ ';', 3, 0, 0x212f _ 0) +NAMED_CHARACTER_REFERENCE(1014, /* e s */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(1015, /* e s */ 'i' _ 'm' _ ';', 3, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(1016, /* e t */ 'a' _ ';', 2, 0, 0x03b7 _ 0) +NAMED_CHARACTER_REFERENCE(1017, /* e t */ 'h', 1, 0, 0x00f0 _ 0) +NAMED_CHARACTER_REFERENCE(1018, /* e t */ 'h' _ ';', 2, 0, 0x00f0 _ 0) +NAMED_CHARACTER_REFERENCE(1019, /* e u */ 'm' _ 'l', 2, 0, 0x00eb _ 0) +NAMED_CHARACTER_REFERENCE(1020, /* e u */ 'm' _ 'l' _ ';', 3, 0, 0x00eb _ 0) +NAMED_CHARACTER_REFERENCE(1021, /* e u */ 'r' _ 'o' _ ';', 3, 0, 0x20ac _ 0) +NAMED_CHARACTER_REFERENCE(1022, /* e x */ 'c' _ 'l' _ ';', 3, 0, 0x0021 _ 0) +NAMED_CHARACTER_REFERENCE(1023, /* e x */ 'i' _ 's' _ 't' _ ';', 4, 0, 0x2203 _ 0) +NAMED_CHARACTER_REFERENCE(1024, /* e x */ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 10, 0, 0x2130 _ 0) +NAMED_CHARACTER_REFERENCE(1025, /* e x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', 11, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(1026, /* f a */ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 12, 0, 0x2252 _ 0) +NAMED_CHARACTER_REFERENCE(1027, /* f c */ 'y' _ ';', 2, 0, 0x0444 _ 0) +NAMED_CHARACTER_REFERENCE(1028, /* f e */ 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0, 0x2640 _ 0) +NAMED_CHARACTER_REFERENCE(1029, /* f f */ 'i' _ 'l' _ 'i' _ 'g' _ ';', 5, 0, 0xfb03 _ 0) +NAMED_CHARACTER_REFERENCE(1030, /* f f */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb00 _ 0) +NAMED_CHARACTER_REFERENCE(1031, /* f f */ 'l' _ 'l' _ 'i' _ 'g' _ ';', 5, 0, 0xfb04 _ 0) +NAMED_CHARACTER_REFERENCE(1032, /* f f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd23) +NAMED_CHARACTER_REFERENCE(1033, /* f i */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb01 _ 0) +NAMED_CHARACTER_REFERENCE(1034, /* f l */ 'a' _ 't' _ ';', 3, 0, 0x266d _ 0) +NAMED_CHARACTER_REFERENCE(1035, /* f l */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb02 _ 0) +NAMED_CHARACTER_REFERENCE(1036, /* f l */ 't' _ 'n' _ 's' _ ';', 4, 0, 0x25b1 _ 0) +NAMED_CHARACTER_REFERENCE(1037, /* f n */ 'o' _ 'f' _ ';', 3, 0, 0x0192 _ 0) +NAMED_CHARACTER_REFERENCE(1038, /* f o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd57) +NAMED_CHARACTER_REFERENCE(1039, /* f o */ 'r' _ 'a' _ 'l' _ 'l' _ ';', 5, 0, 0x2200 _ 0) +NAMED_CHARACTER_REFERENCE(1040, /* f o */ 'r' _ 'k' _ ';', 3, 0, 0x22d4 _ 0) +NAMED_CHARACTER_REFERENCE(1041, /* f o */ 'r' _ 'k' _ 'v' _ ';', 4, 0, 0x2ad9 _ 0) +NAMED_CHARACTER_REFERENCE(1042, /* f p */ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a0d _ 0) +NAMED_CHARACTER_REFERENCE(1043, /* f r */ 'a' _ 'c' _ '1' _ '2', 4, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1044, /* f r */ 'a' _ 'c' _ '1' _ '2' _ ';', 5, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1045, /* f r */ 'a' _ 'c' _ '1' _ '3' _ ';', 5, 0, 0x2153 _ 0) +NAMED_CHARACTER_REFERENCE(1046, /* f r */ 'a' _ 'c' _ '1' _ '4', 4, 0, 0x00bc _ 0) +NAMED_CHARACTER_REFERENCE(1047, /* f r */ 'a' _ 'c' _ '1' _ '4' _ ';', 5, 0, 0x00bc _ 0) +NAMED_CHARACTER_REFERENCE(1048, /* f r */ 'a' _ 'c' _ '1' _ '5' _ ';', 5, 0, 0x2155 _ 0) +NAMED_CHARACTER_REFERENCE(1049, /* f r */ 'a' _ 'c' _ '1' _ '6' _ ';', 5, 0, 0x2159 _ 0) +NAMED_CHARACTER_REFERENCE(1050, /* f r */ 'a' _ 'c' _ '1' _ '8' _ ';', 5, 0, 0x215b _ 0) +NAMED_CHARACTER_REFERENCE(1051, /* f r */ 'a' _ 'c' _ '2' _ '3' _ ';', 5, 0, 0x2154 _ 0) +NAMED_CHARACTER_REFERENCE(1052, /* f r */ 'a' _ 'c' _ '2' _ '5' _ ';', 5, 0, 0x2156 _ 0) +NAMED_CHARACTER_REFERENCE(1053, /* f r */ 'a' _ 'c' _ '3' _ '4', 4, 0, 0x00be _ 0) +NAMED_CHARACTER_REFERENCE(1054, /* f r */ 'a' _ 'c' _ '3' _ '4' _ ';', 5, 0, 0x00be _ 0) +NAMED_CHARACTER_REFERENCE(1055, /* f r */ 'a' _ 'c' _ '3' _ '5' _ ';', 5, 0, 0x2157 _ 0) +NAMED_CHARACTER_REFERENCE(1056, /* f r */ 'a' _ 'c' _ '3' _ '8' _ ';', 5, 0, 0x215c _ 0) +NAMED_CHARACTER_REFERENCE(1057, /* f r */ 'a' _ 'c' _ '4' _ '5' _ ';', 5, 0, 0x2158 _ 0) +NAMED_CHARACTER_REFERENCE(1058, /* f r */ 'a' _ 'c' _ '5' _ '6' _ ';', 5, 0, 0x215a _ 0) +NAMED_CHARACTER_REFERENCE(1059, /* f r */ 'a' _ 'c' _ '5' _ '8' _ ';', 5, 0, 0x215d _ 0) +NAMED_CHARACTER_REFERENCE(1060, /* f r */ 'a' _ 'c' _ '7' _ '8' _ ';', 5, 0, 0x215e _ 0) +NAMED_CHARACTER_REFERENCE(1061, /* f r */ 'a' _ 's' _ 'l' _ ';', 4, 0, 0x2044 _ 0) +NAMED_CHARACTER_REFERENCE(1062, /* f r */ 'o' _ 'w' _ 'n' _ ';', 4, 0, 0x2322 _ 0) +NAMED_CHARACTER_REFERENCE(1063, /* f s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbb) +NAMED_CHARACTER_REFERENCE(1064, /* g E */ ';', 1, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(1065, /* g E */ 'l' _ ';', 2, 0, 0x2a8c _ 0) +NAMED_CHARACTER_REFERENCE(1066, /* g a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x01f5 _ 0) +NAMED_CHARACTER_REFERENCE(1067, /* g a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x03b3 _ 0) +NAMED_CHARACTER_REFERENCE(1068, /* g a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0, 0x03dd _ 0) +NAMED_CHARACTER_REFERENCE(1069, /* g a */ 'p' _ ';', 2, 0, 0x2a86 _ 0) +NAMED_CHARACTER_REFERENCE(1070, /* g b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x011f _ 0) +NAMED_CHARACTER_REFERENCE(1071, /* g c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011d _ 0) +NAMED_CHARACTER_REFERENCE(1072, /* g c */ 'y' _ ';', 2, 0, 0x0433 _ 0) +NAMED_CHARACTER_REFERENCE(1073, /* g d */ 'o' _ 't' _ ';', 3, 0, 0x0121 _ 0) +NAMED_CHARACTER_REFERENCE(1074, /* g e */ ';', 1, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(1075, /* g e */ 'l' _ ';', 2, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(1076, /* g e */ 'q' _ ';', 2, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(1077, /* g e */ 'q' _ 'q' _ ';', 3, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(1078, /* g e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(1079, /* g e */ 's' _ ';', 2, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(1080, /* g e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa9 _ 0) +NAMED_CHARACTER_REFERENCE(1081, /* g e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a80 _ 0) +NAMED_CHARACTER_REFERENCE(1082, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0, 0x2a82 _ 0) +NAMED_CHARACTER_REFERENCE(1083, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 7, 0, 0x2a84 _ 0) +NAMED_CHARACTER_REFERENCE(1084, /* g e */ 's' _ 'l' _ 'e' _ 's' _ ';', 5, 0, 0x2a94 _ 0) +NAMED_CHARACTER_REFERENCE(1085, /* g f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd24) +NAMED_CHARACTER_REFERENCE(1086, /* g g */ ';', 1, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(1087, /* g g */ 'g' _ ';', 2, 0, 0x22d9 _ 0) +NAMED_CHARACTER_REFERENCE(1088, /* g i */ 'm' _ 'e' _ 'l' _ ';', 4, 0, 0x2137 _ 0) +NAMED_CHARACTER_REFERENCE(1089, /* g j */ 'c' _ 'y' _ ';', 3, 0, 0x0453 _ 0) +NAMED_CHARACTER_REFERENCE(1090, /* g l */ ';', 1, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(1091, /* g l */ 'E' _ ';', 2, 0, 0x2a92 _ 0) +NAMED_CHARACTER_REFERENCE(1092, /* g l */ 'a' _ ';', 2, 0, 0x2aa5 _ 0) +NAMED_CHARACTER_REFERENCE(1093, /* g l */ 'j' _ ';', 2, 0, 0x2aa4 _ 0) +NAMED_CHARACTER_REFERENCE(1094, /* g n */ 'E' _ ';', 2, 0, 0x2269 _ 0) +NAMED_CHARACTER_REFERENCE(1095, /* g n */ 'a' _ 'p' _ ';', 3, 0, 0x2a8a _ 0) +NAMED_CHARACTER_REFERENCE(1096, /* g n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0, 0x2a8a _ 0) +NAMED_CHARACTER_REFERENCE(1097, /* g n */ 'e' _ ';', 2, 0, 0x2a88 _ 0) +NAMED_CHARACTER_REFERENCE(1098, /* g n */ 'e' _ 'q' _ ';', 3, 0, 0x2a88 _ 0) +NAMED_CHARACTER_REFERENCE(1099, /* g n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2269 _ 0) +NAMED_CHARACTER_REFERENCE(1100, /* g n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e7 _ 0) +NAMED_CHARACTER_REFERENCE(1101, /* g o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd58) +NAMED_CHARACTER_REFERENCE(1102, /* g r */ 'a' _ 'v' _ 'e' _ ';', 4, 0, 0x0060 _ 0) +NAMED_CHARACTER_REFERENCE(1103, /* g s */ 'c' _ 'r' _ ';', 3, 0, 0x210a _ 0) +NAMED_CHARACTER_REFERENCE(1104, /* g s */ 'i' _ 'm' _ ';', 3, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(1105, /* g s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8e _ 0) +NAMED_CHARACTER_REFERENCE(1106, /* g s */ 'i' _ 'm' _ 'l' _ ';', 4, 0, 0x2a90 _ 0) +NAMED_CHARACTER_REFERENCE(1107, /* g t */ 0, 0, 1, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(1108, /* g t */ ';', 1, 0, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(1109, /* g t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa7 _ 0) +NAMED_CHARACTER_REFERENCE(1110, /* g t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a7a _ 0) +NAMED_CHARACTER_REFERENCE(1111, /* g t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d7 _ 0) +NAMED_CHARACTER_REFERENCE(1112, /* g t */ 'l' _ 'P' _ 'a' _ 'r' _ ';', 5, 0, 0x2995 _ 0) +NAMED_CHARACTER_REFERENCE(1113, /* g t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0, 0x2a7c _ 0) +NAMED_CHARACTER_REFERENCE(1114, /* g t */ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0, 0x2a86 _ 0) +NAMED_CHARACTER_REFERENCE(1115, /* g t */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x2978 _ 0) +NAMED_CHARACTER_REFERENCE(1116, /* g t */ 'r' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x22d7 _ 0) +NAMED_CHARACTER_REFERENCE(1117, /* g t */ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(1118, /* g t */ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 9, 0, 0x2a8c _ 0) +NAMED_CHARACTER_REFERENCE(1119, /* g t */ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(1120, /* g t */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(1121, /* h A */ 'r' _ 'r' _ ';', 3, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(1122, /* h a */ 'i' _ 'r' _ 's' _ 'p' _ ';', 5, 0, 0x200a _ 0) +NAMED_CHARACTER_REFERENCE(1123, /* h a */ 'l' _ 'f' _ ';', 3, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1124, /* h a */ 'm' _ 'i' _ 'l' _ 't' _ ';', 5, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(1125, /* h a */ 'r' _ 'd' _ 'c' _ 'y' _ ';', 5, 0, 0x044a _ 0) +NAMED_CHARACTER_REFERENCE(1126, /* h a */ 'r' _ 'r' _ ';', 3, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(1127, /* h a */ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, 0x2948 _ 0) +NAMED_CHARACTER_REFERENCE(1128, /* h a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x21ad _ 0) +NAMED_CHARACTER_REFERENCE(1129, /* h b */ 'a' _ 'r' _ ';', 3, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1130, /* h c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0125 _ 0) +NAMED_CHARACTER_REFERENCE(1131, /* h e */ 'a' _ 'r' _ 't' _ 's' _ ';', 5, 0, 0x2665 _ 0) +NAMED_CHARACTER_REFERENCE(1132, /* h e */ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2665 _ 0) +NAMED_CHARACTER_REFERENCE(1133, /* h e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0, 0x2026 _ 0) +NAMED_CHARACTER_REFERENCE(1134, /* h e */ 'r' _ 'c' _ 'o' _ 'n' _ ';', 5, 0, 0x22b9 _ 0) +NAMED_CHARACTER_REFERENCE(1135, /* h f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd25) +NAMED_CHARACTER_REFERENCE(1136, /* h k */ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0, 0x2925 _ 0) +NAMED_CHARACTER_REFERENCE(1137, /* h k */ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0, 0x2926 _ 0) +NAMED_CHARACTER_REFERENCE(1138, /* h o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ff _ 0) +NAMED_CHARACTER_REFERENCE(1139, /* h o */ 'm' _ 't' _ 'h' _ 't' _ ';', 5, 0, 0x223b _ 0) +NAMED_CHARACTER_REFERENCE(1140, /* h o */ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x21a9 _ 0) +NAMED_CHARACTER_REFERENCE(1141, /* h o */ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x21aa _ 0) +NAMED_CHARACTER_REFERENCE(1142, /* h o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd59) +NAMED_CHARACTER_REFERENCE(1143, /* h o */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x2015 _ 0) +NAMED_CHARACTER_REFERENCE(1144, /* h s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbd) +NAMED_CHARACTER_REFERENCE(1145, /* h s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1146, /* h s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0127 _ 0) +NAMED_CHARACTER_REFERENCE(1147, /* h y */ 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0, 0x2043 _ 0) +NAMED_CHARACTER_REFERENCE(1148, /* h y */ 'p' _ 'h' _ 'e' _ 'n' _ ';', 5, 0, 0x2010 _ 0) +NAMED_CHARACTER_REFERENCE(1149, /* i a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00ed _ 0) +NAMED_CHARACTER_REFERENCE(1150, /* i a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00ed _ 0) +NAMED_CHARACTER_REFERENCE(1151, /* i c */ ';', 1, 0, 0x2063 _ 0) +NAMED_CHARACTER_REFERENCE(1152, /* i c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ee _ 0) +NAMED_CHARACTER_REFERENCE(1153, /* i c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ee _ 0) +NAMED_CHARACTER_REFERENCE(1154, /* i c */ 'y' _ ';', 2, 0, 0x0438 _ 0) +NAMED_CHARACTER_REFERENCE(1155, /* i e */ 'c' _ 'y' _ ';', 3, 0, 0x0435 _ 0) +NAMED_CHARACTER_REFERENCE(1156, /* i e */ 'x' _ 'c' _ 'l', 3, 0, 0x00a1 _ 0) +NAMED_CHARACTER_REFERENCE(1157, /* i e */ 'x' _ 'c' _ 'l' _ ';', 4, 0, 0x00a1 _ 0) +NAMED_CHARACTER_REFERENCE(1158, /* i f */ 'f' _ ';', 2, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(1159, /* i f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd26) +NAMED_CHARACTER_REFERENCE(1160, /* i g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00ec _ 0) +NAMED_CHARACTER_REFERENCE(1161, /* i g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00ec _ 0) +NAMED_CHARACTER_REFERENCE(1162, /* i i */ ';', 1, 0, 0x2148 _ 0) +NAMED_CHARACTER_REFERENCE(1163, /* i i */ 'i' _ 'i' _ 'n' _ 't' _ ';', 5, 0, 0x2a0c _ 0) +NAMED_CHARACTER_REFERENCE(1164, /* i i */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x222d _ 0) +NAMED_CHARACTER_REFERENCE(1165, /* i i */ 'n' _ 'f' _ 'i' _ 'n' _ ';', 5, 0, 0x29dc _ 0) +NAMED_CHARACTER_REFERENCE(1166, /* i i */ 'o' _ 't' _ 'a' _ ';', 4, 0, 0x2129 _ 0) +NAMED_CHARACTER_REFERENCE(1167, /* i j */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0133 _ 0) +NAMED_CHARACTER_REFERENCE(1168, /* i m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012b _ 0) +NAMED_CHARACTER_REFERENCE(1169, /* i m */ 'a' _ 'g' _ 'e' _ ';', 4, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(1170, /* i m */ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0, 0x2110 _ 0) +NAMED_CHARACTER_REFERENCE(1171, /* i m */ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(1172, /* i m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0131 _ 0) +NAMED_CHARACTER_REFERENCE(1173, /* i m */ 'o' _ 'f' _ ';', 3, 0, 0x22b7 _ 0) +NAMED_CHARACTER_REFERENCE(1174, /* i m */ 'p' _ 'e' _ 'd' _ ';', 4, 0, 0x01b5 _ 0) +NAMED_CHARACTER_REFERENCE(1175, /* i n */ ';', 1, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1176, /* i n */ 'c' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, 0x2105 _ 0) +NAMED_CHARACTER_REFERENCE(1177, /* i n */ 'f' _ 'i' _ 'n' _ ';', 4, 0, 0x221e _ 0) +NAMED_CHARACTER_REFERENCE(1178, /* i n */ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 7, 0, 0x29dd _ 0) +NAMED_CHARACTER_REFERENCE(1179, /* i n */ 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x0131 _ 0) +NAMED_CHARACTER_REFERENCE(1180, /* i n */ 't' _ ';', 2, 0, 0x222b _ 0) +NAMED_CHARACTER_REFERENCE(1181, /* i n */ 't' _ 'c' _ 'a' _ 'l' _ ';', 5, 0, 0x22ba _ 0) +NAMED_CHARACTER_REFERENCE(1182, /* i n */ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 7, 0, 0x2124 _ 0) +NAMED_CHARACTER_REFERENCE(1183, /* i n */ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 7, 0, 0x22ba _ 0) +NAMED_CHARACTER_REFERENCE(1184, /* i n */ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0, 0x2a17 _ 0) +NAMED_CHARACTER_REFERENCE(1185, /* i n */ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0, 0x2a3c _ 0) +NAMED_CHARACTER_REFERENCE(1186, /* i o */ 'c' _ 'y' _ ';', 3, 0, 0x0451 _ 0) +NAMED_CHARACTER_REFERENCE(1187, /* i o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012f _ 0) +NAMED_CHARACTER_REFERENCE(1188, /* i o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5a) +NAMED_CHARACTER_REFERENCE(1189, /* i o */ 't' _ 'a' _ ';', 3, 0, 0x03b9 _ 0) +NAMED_CHARACTER_REFERENCE(1190, /* i p */ 'r' _ 'o' _ 'd' _ ';', 4, 0, 0x2a3c _ 0) +NAMED_CHARACTER_REFERENCE(1191, /* i q */ 'u' _ 'e' _ 's' _ 't', 4, 0, 0x00bf _ 0) +NAMED_CHARACTER_REFERENCE(1192, /* i q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0, 0x00bf _ 0) +NAMED_CHARACTER_REFERENCE(1193, /* i s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbe) +NAMED_CHARACTER_REFERENCE(1194, /* i s */ 'i' _ 'n' _ ';', 3, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1195, /* i s */ 'i' _ 'n' _ 'E' _ ';', 4, 0, 0x22f9 _ 0) +NAMED_CHARACTER_REFERENCE(1196, /* i s */ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x22f5 _ 0) +NAMED_CHARACTER_REFERENCE(1197, /* i s */ 'i' _ 'n' _ 's' _ ';', 4, 0, 0x22f4 _ 0) +NAMED_CHARACTER_REFERENCE(1198, /* i s */ 'i' _ 'n' _ 's' _ 'v' _ ';', 5, 0, 0x22f3 _ 0) +NAMED_CHARACTER_REFERENCE(1199, /* i s */ 'i' _ 'n' _ 'v' _ ';', 4, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1200, /* i t */ ';', 1, 0, 0x2062 _ 0) +NAMED_CHARACTER_REFERENCE(1201, /* i t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0129 _ 0) +NAMED_CHARACTER_REFERENCE(1202, /* i u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0456 _ 0) +NAMED_CHARACTER_REFERENCE(1203, /* i u */ 'm' _ 'l', 2, 0, 0x00ef _ 0) +NAMED_CHARACTER_REFERENCE(1204, /* i u */ 'm' _ 'l' _ ';', 3, 0, 0x00ef _ 0) +NAMED_CHARACTER_REFERENCE(1205, /* j c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0135 _ 0) +NAMED_CHARACTER_REFERENCE(1206, /* j c */ 'y' _ ';', 2, 0, 0x0439 _ 0) +NAMED_CHARACTER_REFERENCE(1207, /* j f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd27) +NAMED_CHARACTER_REFERENCE(1208, /* j m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0237 _ 0) +NAMED_CHARACTER_REFERENCE(1209, /* j o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5b) +NAMED_CHARACTER_REFERENCE(1210, /* j s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbf) +NAMED_CHARACTER_REFERENCE(1211, /* j s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0, 0x0458 _ 0) +NAMED_CHARACTER_REFERENCE(1212, /* j u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0454 _ 0) +NAMED_CHARACTER_REFERENCE(1213, /* k a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x03ba _ 0) +NAMED_CHARACTER_REFERENCE(1214, /* k a */ 'p' _ 'p' _ 'a' _ 'v' _ ';', 5, 0, 0x03f0 _ 0) +NAMED_CHARACTER_REFERENCE(1215, /* k c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0137 _ 0) +NAMED_CHARACTER_REFERENCE(1216, /* k c */ 'y' _ ';', 2, 0, 0x043a _ 0) +NAMED_CHARACTER_REFERENCE(1217, /* k f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd28) +NAMED_CHARACTER_REFERENCE(1218, /* k g */ 'r' _ 'e' _ 'e' _ 'n' _ ';', 5, 0, 0x0138 _ 0) +NAMED_CHARACTER_REFERENCE(1219, /* k h */ 'c' _ 'y' _ ';', 3, 0, 0x0445 _ 0) +NAMED_CHARACTER_REFERENCE(1220, /* k j */ 'c' _ 'y' _ ';', 3, 0, 0x045c _ 0) +NAMED_CHARACTER_REFERENCE(1221, /* k o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5c) +NAMED_CHARACTER_REFERENCE(1222, /* k s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc0) +NAMED_CHARACTER_REFERENCE(1223, /* l A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21da _ 0) +NAMED_CHARACTER_REFERENCE(1224, /* l A */ 'r' _ 'r' _ ';', 3, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(1225, /* l A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x291b _ 0) +NAMED_CHARACTER_REFERENCE(1226, /* l B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290e _ 0) +NAMED_CHARACTER_REFERENCE(1227, /* l E */ ';', 1, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(1228, /* l E */ 'g' _ ';', 2, 0, 0x2a8b _ 0) +NAMED_CHARACTER_REFERENCE(1229, /* l H */ 'a' _ 'r' _ ';', 3, 0, 0x2962 _ 0) +NAMED_CHARACTER_REFERENCE(1230, /* l a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x013a _ 0) +NAMED_CHARACTER_REFERENCE(1231, /* l a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0, 0x29b4 _ 0) +NAMED_CHARACTER_REFERENCE(1232, /* l a */ 'g' _ 'r' _ 'a' _ 'n' _ ';', 5, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(1233, /* l a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0, 0x03bb _ 0) +NAMED_CHARACTER_REFERENCE(1234, /* l a */ 'n' _ 'g' _ ';', 3, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(1235, /* l a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2991 _ 0) +NAMED_CHARACTER_REFERENCE(1236, /* l a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(1237, /* l a */ 'p' _ ';', 2, 0, 0x2a85 _ 0) +NAMED_CHARACTER_REFERENCE(1238, /* l a */ 'q' _ 'u' _ 'o', 3, 0, 0x00ab _ 0) +NAMED_CHARACTER_REFERENCE(1239, /* l a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00ab _ 0) +NAMED_CHARACTER_REFERENCE(1240, /* l a */ 'r' _ 'r' _ ';', 3, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1241, /* l a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e4 _ 0) +NAMED_CHARACTER_REFERENCE(1242, /* l a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0, 0x291f _ 0) +NAMED_CHARACTER_REFERENCE(1243, /* l a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0, 0x291d _ 0) +NAMED_CHARACTER_REFERENCE(1244, /* l a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x21a9 _ 0) +NAMED_CHARACTER_REFERENCE(1245, /* l a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0, 0x21ab _ 0) +NAMED_CHARACTER_REFERENCE(1246, /* l a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0, 0x2939 _ 0) +NAMED_CHARACTER_REFERENCE(1247, /* l a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2973 _ 0) +NAMED_CHARACTER_REFERENCE(1248, /* l a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, 0x21a2 _ 0) +NAMED_CHARACTER_REFERENCE(1249, /* l a */ 't' _ ';', 2, 0, 0x2aab _ 0) +NAMED_CHARACTER_REFERENCE(1250, /* l a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x2919 _ 0) +NAMED_CHARACTER_REFERENCE(1251, /* l a */ 't' _ 'e' _ ';', 3, 0, 0x2aad _ 0) +NAMED_CHARACTER_REFERENCE(1252, /* l b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290c _ 0) +NAMED_CHARACTER_REFERENCE(1253, /* l b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2772 _ 0) +NAMED_CHARACTER_REFERENCE(1254, /* l b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0, 0x007b _ 0) +NAMED_CHARACTER_REFERENCE(1255, /* l b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0, 0x005b _ 0) +NAMED_CHARACTER_REFERENCE(1256, /* l b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298b _ 0) +NAMED_CHARACTER_REFERENCE(1257, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0, 0x298f _ 0) +NAMED_CHARACTER_REFERENCE(1258, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0, 0x298d _ 0) +NAMED_CHARACTER_REFERENCE(1259, /* l c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x013e _ 0) +NAMED_CHARACTER_REFERENCE(1260, /* l c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x013c _ 0) +NAMED_CHARACTER_REFERENCE(1261, /* l c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2308 _ 0) +NAMED_CHARACTER_REFERENCE(1262, /* l c */ 'u' _ 'b' _ ';', 3, 0, 0x007b _ 0) +NAMED_CHARACTER_REFERENCE(1263, /* l c */ 'y' _ ';', 2, 0, 0x043b _ 0) +NAMED_CHARACTER_REFERENCE(1264, /* l d */ 'c' _ 'a' _ ';', 3, 0, 0x2936 _ 0) +NAMED_CHARACTER_REFERENCE(1265, /* l d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201c _ 0) +NAMED_CHARACTER_REFERENCE(1266, /* l d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x201e _ 0) +NAMED_CHARACTER_REFERENCE(1267, /* l d */ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2967 _ 0) +NAMED_CHARACTER_REFERENCE(1268, /* l d */ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0, 0x294b _ 0) +NAMED_CHARACTER_REFERENCE(1269, /* l d */ 's' _ 'h' _ ';', 3, 0, 0x21b2 _ 0) +NAMED_CHARACTER_REFERENCE(1270, /* l e */ ';', 1, 0, 0x2264 _ 0) +NAMED_CHARACTER_REFERENCE(1271, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1272, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 12, 0, 0x21a2 _ 0) +NAMED_CHARACTER_REFERENCE(1273, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(1274, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 12, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(1275, /* l e */ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0, 0x21c7 _ 0) +NAMED_CHARACTER_REFERENCE(1276, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(1277, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(1278, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(1279, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x21ad _ 0) +NAMED_CHARACTER_REFERENCE(1280, /* l e */ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0, 0x22cb _ 0) +NAMED_CHARACTER_REFERENCE(1281, /* l e */ 'g' _ ';', 2, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(1282, /* l e */ 'q' _ ';', 2, 0, 0x2264 _ 0) +NAMED_CHARACTER_REFERENCE(1283, /* l e */ 'q' _ 'q' _ ';', 3, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(1284, /* l e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(1285, /* l e */ 's' _ ';', 2, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(1286, /* l e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa8 _ 0) +NAMED_CHARACTER_REFERENCE(1287, /* l e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a7f _ 0) +NAMED_CHARACTER_REFERENCE(1288, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0, 0x2a81 _ 0) +NAMED_CHARACTER_REFERENCE(1289, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 7, 0, 0x2a83 _ 0) +NAMED_CHARACTER_REFERENCE(1290, /* l e */ 's' _ 'g' _ 'e' _ 's' _ ';', 5, 0, 0x2a93 _ 0) +NAMED_CHARACTER_REFERENCE(1291, /* l e */ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, 0x2a85 _ 0) +NAMED_CHARACTER_REFERENCE(1292, /* l e */ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x22d6 _ 0) +NAMED_CHARACTER_REFERENCE(1293, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 8, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(1294, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 9, 0, 0x2a8b _ 0) +NAMED_CHARACTER_REFERENCE(1295, /* l e */ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 6, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(1296, /* l e */ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(1297, /* l f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297c _ 0) +NAMED_CHARACTER_REFERENCE(1298, /* l f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0, 0x230a _ 0) +NAMED_CHARACTER_REFERENCE(1299, /* l f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd29) +NAMED_CHARACTER_REFERENCE(1300, /* l g */ ';', 1, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(1301, /* l g */ 'E' _ ';', 2, 0, 0x2a91 _ 0) +NAMED_CHARACTER_REFERENCE(1302, /* l h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(1303, /* l h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(1304, /* l h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0, 0x296a _ 0) +NAMED_CHARACTER_REFERENCE(1305, /* l h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2584 _ 0) +NAMED_CHARACTER_REFERENCE(1306, /* l j */ 'c' _ 'y' _ ';', 3, 0, 0x0459 _ 0) +NAMED_CHARACTER_REFERENCE(1307, /* l l */ ';', 1, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(1308, /* l l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c7 _ 0) +NAMED_CHARACTER_REFERENCE(1309, /* l l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231e _ 0) +NAMED_CHARACTER_REFERENCE(1310, /* l l */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0, 0x296b _ 0) +NAMED_CHARACTER_REFERENCE(1311, /* l l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25fa _ 0) +NAMED_CHARACTER_REFERENCE(1312, /* l m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x0140 _ 0) +NAMED_CHARACTER_REFERENCE(1313, /* l m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0, 0x23b0 _ 0) +NAMED_CHARACTER_REFERENCE(1314, /* l m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0, 0x23b0 _ 0) +NAMED_CHARACTER_REFERENCE(1315, /* l n */ 'E' _ ';', 2, 0, 0x2268 _ 0) +NAMED_CHARACTER_REFERENCE(1316, /* l n */ 'a' _ 'p' _ ';', 3, 0, 0x2a89 _ 0) +NAMED_CHARACTER_REFERENCE(1317, /* l n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0, 0x2a89 _ 0) +NAMED_CHARACTER_REFERENCE(1318, /* l n */ 'e' _ ';', 2, 0, 0x2a87 _ 0) +NAMED_CHARACTER_REFERENCE(1319, /* l n */ 'e' _ 'q' _ ';', 3, 0, 0x2a87 _ 0) +NAMED_CHARACTER_REFERENCE(1320, /* l n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2268 _ 0) +NAMED_CHARACTER_REFERENCE(1321, /* l n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e6 _ 0) +NAMED_CHARACTER_REFERENCE(1322, /* l o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ec _ 0) +NAMED_CHARACTER_REFERENCE(1323, /* l o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fd _ 0) +NAMED_CHARACTER_REFERENCE(1324, /* l o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e6 _ 0) +NAMED_CHARACTER_REFERENCE(1325, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(1326, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(1327, /* l o */ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 9, 0, 0x27fc _ 0) +NAMED_CHARACTER_REFERENCE(1328, /* l o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(1329, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0, 0x21ab _ 0) +NAMED_CHARACTER_REFERENCE(1330, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0, 0x21ac _ 0) +NAMED_CHARACTER_REFERENCE(1331, /* l o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2985 _ 0) +NAMED_CHARACTER_REFERENCE(1332, /* l o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5d) +NAMED_CHARACTER_REFERENCE(1333, /* l o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a2d _ 0) +NAMED_CHARACTER_REFERENCE(1334, /* l o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0, 0x2a34 _ 0) +NAMED_CHARACTER_REFERENCE(1335, /* l o */ 'w' _ 'a' _ 's' _ 't' _ ';', 5, 0, 0x2217 _ 0) +NAMED_CHARACTER_REFERENCE(1336, /* l o */ 'w' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x005f _ 0) +NAMED_CHARACTER_REFERENCE(1337, /* l o */ 'z' _ ';', 2, 0, 0x25ca _ 0) +NAMED_CHARACTER_REFERENCE(1338, /* l o */ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 6, 0, 0x25ca _ 0) +NAMED_CHARACTER_REFERENCE(1339, /* l o */ 'z' _ 'f' _ ';', 3, 0, 0x29eb _ 0) +NAMED_CHARACTER_REFERENCE(1340, /* l p */ 'a' _ 'r' _ ';', 3, 0, 0x0028 _ 0) +NAMED_CHARACTER_REFERENCE(1341, /* l p */ 'a' _ 'r' _ 'l' _ 't' _ ';', 5, 0, 0x2993 _ 0) +NAMED_CHARACTER_REFERENCE(1342, /* l r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(1343, /* l r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231f _ 0) +NAMED_CHARACTER_REFERENCE(1344, /* l r */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(1345, /* l r */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0, 0x296d _ 0) +NAMED_CHARACTER_REFERENCE(1346, /* l r */ 'm' _ ';', 2, 0, 0x200e _ 0) +NAMED_CHARACTER_REFERENCE(1347, /* l r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22bf _ 0) +NAMED_CHARACTER_REFERENCE(1348, /* l s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0, 0x2039 _ 0) +NAMED_CHARACTER_REFERENCE(1349, /* l s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc1) +NAMED_CHARACTER_REFERENCE(1350, /* l s */ 'h' _ ';', 2, 0, 0x21b0 _ 0) +NAMED_CHARACTER_REFERENCE(1351, /* l s */ 'i' _ 'm' _ ';', 3, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(1352, /* l s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8d _ 0) +NAMED_CHARACTER_REFERENCE(1353, /* l s */ 'i' _ 'm' _ 'g' _ ';', 4, 0, 0x2a8f _ 0) +NAMED_CHARACTER_REFERENCE(1354, /* l s */ 'q' _ 'b' _ ';', 3, 0, 0x005b _ 0) +NAMED_CHARACTER_REFERENCE(1355, /* l s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2018 _ 0) +NAMED_CHARACTER_REFERENCE(1356, /* l s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x201a _ 0) +NAMED_CHARACTER_REFERENCE(1357, /* l s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0142 _ 0) +NAMED_CHARACTER_REFERENCE(1358, /* l t */ 0, 0, 1, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(1359, /* l t */ ';', 1, 0, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(1360, /* l t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa6 _ 0) +NAMED_CHARACTER_REFERENCE(1361, /* l t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a79 _ 0) +NAMED_CHARACTER_REFERENCE(1362, /* l t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d6 _ 0) +NAMED_CHARACTER_REFERENCE(1363, /* l t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0, 0x22cb _ 0) +NAMED_CHARACTER_REFERENCE(1364, /* l t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x22c9 _ 0) +NAMED_CHARACTER_REFERENCE(1365, /* l t */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x2976 _ 0) +NAMED_CHARACTER_REFERENCE(1366, /* l t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0, 0x2a7b _ 0) +NAMED_CHARACTER_REFERENCE(1367, /* l t */ 'r' _ 'P' _ 'a' _ 'r' _ ';', 5, 0, 0x2996 _ 0) +NAMED_CHARACTER_REFERENCE(1368, /* l t */ 'r' _ 'i' _ ';', 3, 0, 0x25c3 _ 0) +NAMED_CHARACTER_REFERENCE(1369, /* l t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(1370, /* l t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25c2 _ 0) +NAMED_CHARACTER_REFERENCE(1371, /* l u */ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0, 0x294a _ 0) +NAMED_CHARACTER_REFERENCE(1372, /* l u */ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2966 _ 0) +NAMED_CHARACTER_REFERENCE(1373, /* m D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x223a _ 0) +NAMED_CHARACTER_REFERENCE(1374, /* m a */ 'c' _ 'r', 2, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1375, /* m a */ 'c' _ 'r' _ ';', 3, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1376, /* m a */ 'l' _ 'e' _ ';', 3, 0, 0x2642 _ 0) +NAMED_CHARACTER_REFERENCE(1377, /* m a */ 'l' _ 't' _ ';', 3, 0, 0x2720 _ 0) +NAMED_CHARACTER_REFERENCE(1378, /* m a */ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 6, 0, 0x2720 _ 0) +NAMED_CHARACTER_REFERENCE(1379, /* m a */ 'p' _ ';', 2, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(1380, /* m a */ 'p' _ 's' _ 't' _ 'o' _ ';', 5, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(1381, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 9, 0, 0x21a7 _ 0) +NAMED_CHARACTER_REFERENCE(1382, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 9, 0, 0x21a4 _ 0) +NAMED_CHARACTER_REFERENCE(1383, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 7, 0, 0x21a5 _ 0) +NAMED_CHARACTER_REFERENCE(1384, /* m a */ 'r' _ 'k' _ 'e' _ 'r' _ ';', 5, 0, 0x25ae _ 0) +NAMED_CHARACTER_REFERENCE(1385, /* m c */ 'o' _ 'm' _ 'm' _ 'a' _ ';', 5, 0, 0x2a29 _ 0) +NAMED_CHARACTER_REFERENCE(1386, /* m c */ 'y' _ ';', 2, 0, 0x043c _ 0) +NAMED_CHARACTER_REFERENCE(1387, /* m d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2014 _ 0) +NAMED_CHARACTER_REFERENCE(1388, /* m e */ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0, 0x2221 _ 0) +NAMED_CHARACTER_REFERENCE(1389, /* m f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2a) +NAMED_CHARACTER_REFERENCE(1390, /* m h */ 'o' _ ';', 2, 0, 0x2127 _ 0) +NAMED_CHARACTER_REFERENCE(1391, /* m i */ 'c' _ 'r' _ 'o', 3, 0, 0x00b5 _ 0) +NAMED_CHARACTER_REFERENCE(1392, /* m i */ 'c' _ 'r' _ 'o' _ ';', 4, 0, 0x00b5 _ 0) +NAMED_CHARACTER_REFERENCE(1393, /* m i */ 'd' _ ';', 2, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1394, /* m i */ 'd' _ 'a' _ 's' _ 't' _ ';', 5, 0, 0x002a _ 0) +NAMED_CHARACTER_REFERENCE(1395, /* m i */ 'd' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, 0x2af0 _ 0) +NAMED_CHARACTER_REFERENCE(1396, /* m i */ 'd' _ 'd' _ 'o' _ 't', 4, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(1397, /* m i */ 'd' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(1398, /* m i */ 'n' _ 'u' _ 's' _ ';', 4, 0, 0x2212 _ 0) +NAMED_CHARACTER_REFERENCE(1399, /* m i */ 'n' _ 'u' _ 's' _ 'b' _ ';', 5, 0, 0x229f _ 0) +NAMED_CHARACTER_REFERENCE(1400, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ ';', 5, 0, 0x2238 _ 0) +NAMED_CHARACTER_REFERENCE(1401, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 6, 0, 0x2a2a _ 0) +NAMED_CHARACTER_REFERENCE(1402, /* m l */ 'c' _ 'p' _ ';', 3, 0, 0x2adb _ 0) +NAMED_CHARACTER_REFERENCE(1403, /* m l */ 'd' _ 'r' _ ';', 3, 0, 0x2026 _ 0) +NAMED_CHARACTER_REFERENCE(1404, /* m n */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(1405, /* m o */ 'd' _ 'e' _ 'l' _ 's' _ ';', 5, 0, 0x22a7 _ 0) +NAMED_CHARACTER_REFERENCE(1406, /* m o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5e) +NAMED_CHARACTER_REFERENCE(1407, /* m p */ ';', 1, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(1408, /* m s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc2) +NAMED_CHARACTER_REFERENCE(1409, /* m s */ 't' _ 'p' _ 'o' _ 's' _ ';', 5, 0, 0x223e _ 0) +NAMED_CHARACTER_REFERENCE(1410, /* m u */ ';', 1, 0, 0x03bc _ 0) +NAMED_CHARACTER_REFERENCE(1411, /* m u */ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 7, 0, 0x22b8 _ 0) +NAMED_CHARACTER_REFERENCE(1412, /* m u */ 'm' _ 'a' _ 'p' _ ';', 4, 0, 0x22b8 _ 0) +NAMED_CHARACTER_REFERENCE(1413, /* n L */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21cd _ 0) +NAMED_CHARACTER_REFERENCE(1414, /* n L */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21ce _ 0) +NAMED_CHARACTER_REFERENCE(1415, /* n R */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x21cf _ 0) +NAMED_CHARACTER_REFERENCE(1416, /* n V */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22af _ 0) +NAMED_CHARACTER_REFERENCE(1417, /* n V */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22ae _ 0) +NAMED_CHARACTER_REFERENCE(1418, /* n a */ 'b' _ 'l' _ 'a' _ ';', 4, 0, 0x2207 _ 0) +NAMED_CHARACTER_REFERENCE(1419, /* n a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0144 _ 0) +NAMED_CHARACTER_REFERENCE(1420, /* n a */ 'p' _ ';', 2, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(1421, /* n a */ 'p' _ 'o' _ 's' _ ';', 4, 0, 0x0149 _ 0) +NAMED_CHARACTER_REFERENCE(1422, /* n a */ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 6, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(1423, /* n a */ 't' _ 'u' _ 'r' _ ';', 4, 0, 0x266e _ 0) +NAMED_CHARACTER_REFERENCE(1424, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 6, 0, 0x266e _ 0) +NAMED_CHARACTER_REFERENCE(1425, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 7, 0, 0x2115 _ 0) +NAMED_CHARACTER_REFERENCE(1426, /* n b */ 's' _ 'p', 2, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(1427, /* n b */ 's' _ 'p' _ ';', 3, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(1428, /* n c */ 'a' _ 'p' _ ';', 3, 0, 0x2a43 _ 0) +NAMED_CHARACTER_REFERENCE(1429, /* n c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0148 _ 0) +NAMED_CHARACTER_REFERENCE(1430, /* n c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0146 _ 0) +NAMED_CHARACTER_REFERENCE(1431, /* n c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x2247 _ 0) +NAMED_CHARACTER_REFERENCE(1432, /* n c */ 'u' _ 'p' _ ';', 3, 0, 0x2a42 _ 0) +NAMED_CHARACTER_REFERENCE(1433, /* n c */ 'y' _ ';', 2, 0, 0x043d _ 0) +NAMED_CHARACTER_REFERENCE(1434, /* n d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2013 _ 0) +NAMED_CHARACTER_REFERENCE(1435, /* n e */ ';', 1, 0, 0x2260 _ 0) +NAMED_CHARACTER_REFERENCE(1436, /* n e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d7 _ 0) +NAMED_CHARACTER_REFERENCE(1437, /* n e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2924 _ 0) +NAMED_CHARACTER_REFERENCE(1438, /* n e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(1439, /* n e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(1440, /* n e */ 'q' _ 'u' _ 'i' _ 'v' _ ';', 5, 0, 0x2262 _ 0) +NAMED_CHARACTER_REFERENCE(1441, /* n e */ 's' _ 'e' _ 'a' _ 'r' _ ';', 5, 0, 0x2928 _ 0) +NAMED_CHARACTER_REFERENCE(1442, /* n e */ 'x' _ 'i' _ 's' _ 't' _ ';', 5, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(1443, /* n e */ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 6, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(1444, /* n f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2b) +NAMED_CHARACTER_REFERENCE(1445, /* n g */ 'e' _ ';', 2, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(1446, /* n g */ 'e' _ 'q' _ ';', 3, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(1447, /* n g */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2275 _ 0) +NAMED_CHARACTER_REFERENCE(1448, /* n g */ 't' _ ';', 2, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(1449, /* n g */ 't' _ 'r' _ ';', 3, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(1450, /* n h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21ce _ 0) +NAMED_CHARACTER_REFERENCE(1451, /* n h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ae _ 0) +NAMED_CHARACTER_REFERENCE(1452, /* n h */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2af2 _ 0) +NAMED_CHARACTER_REFERENCE(1453, /* n i */ ';', 1, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(1454, /* n i */ 's' _ ';', 2, 0, 0x22fc _ 0) +NAMED_CHARACTER_REFERENCE(1455, /* n i */ 's' _ 'd' _ ';', 3, 0, 0x22fa _ 0) +NAMED_CHARACTER_REFERENCE(1456, /* n i */ 'v' _ ';', 2, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(1457, /* n j */ 'c' _ 'y' _ ';', 3, 0, 0x045a _ 0) +NAMED_CHARACTER_REFERENCE(1458, /* n l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cd _ 0) +NAMED_CHARACTER_REFERENCE(1459, /* n l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219a _ 0) +NAMED_CHARACTER_REFERENCE(1460, /* n l */ 'd' _ 'r' _ ';', 3, 0, 0x2025 _ 0) +NAMED_CHARACTER_REFERENCE(1461, /* n l */ 'e' _ ';', 2, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(1462, /* n l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x219a _ 0) +NAMED_CHARACTER_REFERENCE(1463, /* n l */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21ae _ 0) +NAMED_CHARACTER_REFERENCE(1464, /* n l */ 'e' _ 'q' _ ';', 3, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(1465, /* n l */ 'e' _ 's' _ 's' _ ';', 4, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(1466, /* n l */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2274 _ 0) +NAMED_CHARACTER_REFERENCE(1467, /* n l */ 't' _ ';', 2, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(1468, /* n l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(1469, /* n l */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(1470, /* n m */ 'i' _ 'd' _ ';', 3, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1471, /* n o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5f) +NAMED_CHARACTER_REFERENCE(1472, /* n o */ 't', 1, 0, 0x00ac _ 0) +NAMED_CHARACTER_REFERENCE(1473, /* n o */ 't' _ ';', 2, 0, 0x00ac _ 0) +NAMED_CHARACTER_REFERENCE(1474, /* n o */ 't' _ 'i' _ 'n' _ ';', 4, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(1475, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 6, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(1476, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 6, 0, 0x22f7 _ 0) +NAMED_CHARACTER_REFERENCE(1477, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 6, 0, 0x22f6 _ 0) +NAMED_CHARACTER_REFERENCE(1478, /* n o */ 't' _ 'n' _ 'i' _ ';', 4, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(1479, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 6, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(1480, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 6, 0, 0x22fe _ 0) +NAMED_CHARACTER_REFERENCE(1481, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 6, 0, 0x22fd _ 0) +NAMED_CHARACTER_REFERENCE(1482, /* n p */ 'a' _ 'r' _ ';', 3, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1483, /* n p */ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 8, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1484, /* n p */ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 6, 0, 0x2a14 _ 0) +NAMED_CHARACTER_REFERENCE(1485, /* n p */ 'r' _ ';', 2, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(1486, /* n p */ 'r' _ 'c' _ 'u' _ 'e' _ ';', 5, 0, 0x22e0 _ 0) +NAMED_CHARACTER_REFERENCE(1487, /* n p */ 'r' _ 'e' _ 'c' _ ';', 4, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(1488, /* n r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cf _ 0) +NAMED_CHARACTER_REFERENCE(1489, /* n r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219b _ 0) +NAMED_CHARACTER_REFERENCE(1490, /* n r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x219b _ 0) +NAMED_CHARACTER_REFERENCE(1491, /* n r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(1492, /* n r */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(1493, /* n s */ 'c' _ ';', 2, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(1494, /* n s */ 'c' _ 'c' _ 'u' _ 'e' _ ';', 5, 0, 0x22e1 _ 0) +NAMED_CHARACTER_REFERENCE(1495, /* n s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc3) +NAMED_CHARACTER_REFERENCE(1496, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 8, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1497, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 13, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1498, /* n s */ 'i' _ 'm' _ ';', 3, 0, 0x2241 _ 0) +NAMED_CHARACTER_REFERENCE(1499, /* n s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(1500, /* n s */ 'i' _ 'm' _ 'e' _ 'q' _ ';', 5, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(1501, /* n s */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1502, /* n s */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1503, /* n s */ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0, 0x22e2 _ 0) +NAMED_CHARACTER_REFERENCE(1504, /* n s */ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0, 0x22e3 _ 0) +NAMED_CHARACTER_REFERENCE(1505, /* n s */ 'u' _ 'b' _ ';', 3, 0, 0x2284 _ 0) +NAMED_CHARACTER_REFERENCE(1506, /* n s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(1507, /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(1508, /* n s */ 'u' _ 'c' _ 'c' _ ';', 4, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(1509, /* n s */ 'u' _ 'p' _ ';', 3, 0, 0x2285 _ 0) +NAMED_CHARACTER_REFERENCE(1510, /* n s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(1511, /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(1512, /* n t */ 'g' _ 'l' _ ';', 3, 0, 0x2279 _ 0) +NAMED_CHARACTER_REFERENCE(1513, /* n t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f1 _ 0) +NAMED_CHARACTER_REFERENCE(1514, /* n t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00f1 _ 0) +NAMED_CHARACTER_REFERENCE(1515, /* n t */ 'l' _ 'g' _ ';', 3, 0, 0x2278 _ 0) +NAMED_CHARACTER_REFERENCE(1516, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(1517, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 14, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(1518, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(1519, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 15, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(1520, /* n u */ ';', 1, 0, 0x03bd _ 0) +NAMED_CHARACTER_REFERENCE(1521, /* n u */ 'm' _ ';', 2, 0, 0x0023 _ 0) +NAMED_CHARACTER_REFERENCE(1522, /* n u */ 'm' _ 'e' _ 'r' _ 'o' _ ';', 5, 0, 0x2116 _ 0) +NAMED_CHARACTER_REFERENCE(1523, /* n u */ 'm' _ 's' _ 'p' _ ';', 4, 0, 0x2007 _ 0) +NAMED_CHARACTER_REFERENCE(1524, /* n v */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22ad _ 0) +NAMED_CHARACTER_REFERENCE(1525, /* n v */ 'H' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x2904 _ 0) +NAMED_CHARACTER_REFERENCE(1526, /* n v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22ac _ 0) +NAMED_CHARACTER_REFERENCE(1527, /* n v */ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0, 0x29de _ 0) +NAMED_CHARACTER_REFERENCE(1528, /* n v */ 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0, 0x2902 _ 0) +NAMED_CHARACTER_REFERENCE(1529, /* n v */ 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0, 0x2903 _ 0) +NAMED_CHARACTER_REFERENCE(1530, /* n w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d6 _ 0) +NAMED_CHARACTER_REFERENCE(1531, /* n w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2923 _ 0) +NAMED_CHARACTER_REFERENCE(1532, /* n w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(1533, /* n w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(1534, /* n w */ 'n' _ 'e' _ 'a' _ 'r' _ ';', 5, 0, 0x2927 _ 0) +NAMED_CHARACTER_REFERENCE(1535, /* o S */ ';', 1, 0, 0x24c8 _ 0) +NAMED_CHARACTER_REFERENCE(1536, /* o a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00f3 _ 0) +NAMED_CHARACTER_REFERENCE(1537, /* o a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00f3 _ 0) +NAMED_CHARACTER_REFERENCE(1538, /* o a */ 's' _ 't' _ ';', 3, 0, 0x229b _ 0) +NAMED_CHARACTER_REFERENCE(1539, /* o c */ 'i' _ 'r' _ ';', 3, 0, 0x229a _ 0) +NAMED_CHARACTER_REFERENCE(1540, /* o c */ 'i' _ 'r' _ 'c', 3, 0, 0x00f4 _ 0) +NAMED_CHARACTER_REFERENCE(1541, /* o c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00f4 _ 0) +NAMED_CHARACTER_REFERENCE(1542, /* o c */ 'y' _ ';', 2, 0, 0x043e _ 0) +NAMED_CHARACTER_REFERENCE(1543, /* o d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x229d _ 0) +NAMED_CHARACTER_REFERENCE(1544, /* o d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0151 _ 0) +NAMED_CHARACTER_REFERENCE(1545, /* o d */ 'i' _ 'v' _ ';', 3, 0, 0x2a38 _ 0) +NAMED_CHARACTER_REFERENCE(1546, /* o d */ 'o' _ 't' _ ';', 3, 0, 0x2299 _ 0) +NAMED_CHARACTER_REFERENCE(1547, /* o d */ 's' _ 'o' _ 'l' _ 'd' _ ';', 5, 0, 0x29bc _ 0) +NAMED_CHARACTER_REFERENCE(1548, /* o e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0153 _ 0) +NAMED_CHARACTER_REFERENCE(1549, /* o f */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29bf _ 0) +NAMED_CHARACTER_REFERENCE(1550, /* o f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2c) +NAMED_CHARACTER_REFERENCE(1551, /* o g */ 'o' _ 'n' _ ';', 3, 0, 0x02db _ 0) +NAMED_CHARACTER_REFERENCE(1552, /* o g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f2 _ 0) +NAMED_CHARACTER_REFERENCE(1553, /* o g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00f2 _ 0) +NAMED_CHARACTER_REFERENCE(1554, /* o g */ 't' _ ';', 2, 0, 0x29c1 _ 0) +NAMED_CHARACTER_REFERENCE(1555, /* o h */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x29b5 _ 0) +NAMED_CHARACTER_REFERENCE(1556, /* o h */ 'm' _ ';', 2, 0, 0x03a9 _ 0) +NAMED_CHARACTER_REFERENCE(1557, /* o i */ 'n' _ 't' _ ';', 3, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(1558, /* o l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ba _ 0) +NAMED_CHARACTER_REFERENCE(1559, /* o l */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29be _ 0) +NAMED_CHARACTER_REFERENCE(1560, /* o l */ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0, 0x29bb _ 0) +NAMED_CHARACTER_REFERENCE(1561, /* o l */ 'i' _ 'n' _ 'e' _ ';', 4, 0, 0x203e _ 0) +NAMED_CHARACTER_REFERENCE(1562, /* o l */ 't' _ ';', 2, 0, 0x29c0 _ 0) +NAMED_CHARACTER_REFERENCE(1563, /* o m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014d _ 0) +NAMED_CHARACTER_REFERENCE(1564, /* o m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03c9 _ 0) +NAMED_CHARACTER_REFERENCE(1565, /* o m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0, 0x03bf _ 0) +NAMED_CHARACTER_REFERENCE(1566, /* o m */ 'i' _ 'd' _ ';', 3, 0, 0x29b6 _ 0) +NAMED_CHARACTER_REFERENCE(1567, /* o m */ 'i' _ 'n' _ 'u' _ 's' _ ';', 5, 0, 0x2296 _ 0) +NAMED_CHARACTER_REFERENCE(1568, /* o o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd60) +NAMED_CHARACTER_REFERENCE(1569, /* o p */ 'a' _ 'r' _ ';', 3, 0, 0x29b7 _ 0) +NAMED_CHARACTER_REFERENCE(1570, /* o p */ 'e' _ 'r' _ 'p' _ ';', 4, 0, 0x29b9 _ 0) +NAMED_CHARACTER_REFERENCE(1571, /* o p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2295 _ 0) +NAMED_CHARACTER_REFERENCE(1572, /* o r */ ';', 1, 0, 0x2228 _ 0) +NAMED_CHARACTER_REFERENCE(1573, /* o r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21bb _ 0) +NAMED_CHARACTER_REFERENCE(1574, /* o r */ 'd' _ ';', 2, 0, 0x2a5d _ 0) +NAMED_CHARACTER_REFERENCE(1575, /* o r */ 'd' _ 'e' _ 'r' _ ';', 4, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1576, /* o r */ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 6, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1577, /* o r */ 'd' _ 'f', 2, 0, 0x00aa _ 0) +NAMED_CHARACTER_REFERENCE(1578, /* o r */ 'd' _ 'f' _ ';', 3, 0, 0x00aa _ 0) +NAMED_CHARACTER_REFERENCE(1579, /* o r */ 'd' _ 'm', 2, 0, 0x00ba _ 0) +NAMED_CHARACTER_REFERENCE(1580, /* o r */ 'd' _ 'm' _ ';', 3, 0, 0x00ba _ 0) +NAMED_CHARACTER_REFERENCE(1581, /* o r */ 'i' _ 'g' _ 'o' _ 'f' _ ';', 5, 0, 0x22b6 _ 0) +NAMED_CHARACTER_REFERENCE(1582, /* o r */ 'o' _ 'r' _ ';', 3, 0, 0x2a56 _ 0) +NAMED_CHARACTER_REFERENCE(1583, /* o r */ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 6, 0, 0x2a57 _ 0) +NAMED_CHARACTER_REFERENCE(1584, /* o r */ 'v' _ ';', 2, 0, 0x2a5b _ 0) +NAMED_CHARACTER_REFERENCE(1585, /* o s */ 'c' _ 'r' _ ';', 3, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1586, /* o s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00f8 _ 0) +NAMED_CHARACTER_REFERENCE(1587, /* o s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x00f8 _ 0) +NAMED_CHARACTER_REFERENCE(1588, /* o s */ 'o' _ 'l' _ ';', 3, 0, 0x2298 _ 0) +NAMED_CHARACTER_REFERENCE(1589, /* o t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f5 _ 0) +NAMED_CHARACTER_REFERENCE(1590, /* o t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00f5 _ 0) +NAMED_CHARACTER_REFERENCE(1591, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x2297 _ 0) +NAMED_CHARACTER_REFERENCE(1592, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 7, 0, 0x2a36 _ 0) +NAMED_CHARACTER_REFERENCE(1593, /* o u */ 'm' _ 'l', 2, 0, 0x00f6 _ 0) +NAMED_CHARACTER_REFERENCE(1594, /* o u */ 'm' _ 'l' _ ';', 3, 0, 0x00f6 _ 0) +NAMED_CHARACTER_REFERENCE(1595, /* o v */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x233d _ 0) +NAMED_CHARACTER_REFERENCE(1596, /* p a */ 'r' _ ';', 2, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1597, /* p a */ 'r' _ 'a', 2, 0, 0x00b6 _ 0) +NAMED_CHARACTER_REFERENCE(1598, /* p a */ 'r' _ 'a' _ ';', 3, 0, 0x00b6 _ 0) +NAMED_CHARACTER_REFERENCE(1599, /* p a */ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 7, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1600, /* p a */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2af3 _ 0) +NAMED_CHARACTER_REFERENCE(1601, /* p a */ 'r' _ 's' _ 'l' _ ';', 4, 0, 0x2afd _ 0) +NAMED_CHARACTER_REFERENCE(1602, /* p a */ 'r' _ 't' _ ';', 3, 0, 0x2202 _ 0) +NAMED_CHARACTER_REFERENCE(1603, /* p c */ 'y' _ ';', 2, 0, 0x043f _ 0) +NAMED_CHARACTER_REFERENCE(1604, /* p e */ 'r' _ 'c' _ 'n' _ 't' _ ';', 5, 0, 0x0025 _ 0) +NAMED_CHARACTER_REFERENCE(1605, /* p e */ 'r' _ 'i' _ 'o' _ 'd' _ ';', 5, 0, 0x002e _ 0) +NAMED_CHARACTER_REFERENCE(1606, /* p e */ 'r' _ 'm' _ 'i' _ 'l' _ ';', 5, 0, 0x2030 _ 0) +NAMED_CHARACTER_REFERENCE(1607, /* p e */ 'r' _ 'p' _ ';', 3, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(1608, /* p e */ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 6, 0, 0x2031 _ 0) +NAMED_CHARACTER_REFERENCE(1609, /* p f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2d) +NAMED_CHARACTER_REFERENCE(1610, /* p h */ 'i' _ ';', 2, 0, 0x03c6 _ 0) +NAMED_CHARACTER_REFERENCE(1611, /* p h */ 'i' _ 'v' _ ';', 3, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(1612, /* p h */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(1613, /* p h */ 'o' _ 'n' _ 'e' _ ';', 4, 0, 0x260e _ 0) +NAMED_CHARACTER_REFERENCE(1614, /* p i */ ';', 1, 0, 0x03c0 _ 0) +NAMED_CHARACTER_REFERENCE(1615, /* p i */ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0, 0x22d4 _ 0) +NAMED_CHARACTER_REFERENCE(1616, /* p i */ 'v' _ ';', 2, 0, 0x03d6 _ 0) +NAMED_CHARACTER_REFERENCE(1617, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ ';', 5, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1618, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 6, 0, 0x210e _ 0) +NAMED_CHARACTER_REFERENCE(1619, /* p l */ 'a' _ 'n' _ 'k' _ 'v' _ ';', 5, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1620, /* p l */ 'u' _ 's' _ ';', 3, 0, 0x002b _ 0) +NAMED_CHARACTER_REFERENCE(1621, /* p l */ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 7, 0, 0x2a23 _ 0) +NAMED_CHARACTER_REFERENCE(1622, /* p l */ 'u' _ 's' _ 'b' _ ';', 4, 0, 0x229e _ 0) +NAMED_CHARACTER_REFERENCE(1623, /* p l */ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, 0x2a22 _ 0) +NAMED_CHARACTER_REFERENCE(1624, /* p l */ 'u' _ 's' _ 'd' _ 'o' _ ';', 5, 0, 0x2214 _ 0) +NAMED_CHARACTER_REFERENCE(1625, /* p l */ 'u' _ 's' _ 'd' _ 'u' _ ';', 5, 0, 0x2a25 _ 0) +NAMED_CHARACTER_REFERENCE(1626, /* p l */ 'u' _ 's' _ 'e' _ ';', 4, 0, 0x2a72 _ 0) +NAMED_CHARACTER_REFERENCE(1627, /* p l */ 'u' _ 's' _ 'm' _ 'n', 4, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1628, /* p l */ 'u' _ 's' _ 'm' _ 'n' _ ';', 5, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1629, /* p l */ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2a26 _ 0) +NAMED_CHARACTER_REFERENCE(1630, /* p l */ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 6, 0, 0x2a27 _ 0) +NAMED_CHARACTER_REFERENCE(1631, /* p m */ ';', 1, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1632, /* p o */ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a15 _ 0) +NAMED_CHARACTER_REFERENCE(1633, /* p o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd61) +NAMED_CHARACTER_REFERENCE(1634, /* p o */ 'u' _ 'n' _ 'd', 3, 0, 0x00a3 _ 0) +NAMED_CHARACTER_REFERENCE(1635, /* p o */ 'u' _ 'n' _ 'd' _ ';', 4, 0, 0x00a3 _ 0) +NAMED_CHARACTER_REFERENCE(1636, /* p r */ ';', 1, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(1637, /* p r */ 'E' _ ';', 2, 0, 0x2ab3 _ 0) +NAMED_CHARACTER_REFERENCE(1638, /* p r */ 'a' _ 'p' _ ';', 3, 0, 0x2ab7 _ 0) +NAMED_CHARACTER_REFERENCE(1639, /* p r */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(1640, /* p r */ 'e' _ ';', 2, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(1641, /* p r */ 'e' _ 'c' _ ';', 3, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(1642, /* p r */ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, 0x2ab7 _ 0) +NAMED_CHARACTER_REFERENCE(1643, /* p r */ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(1644, /* p r */ 'e' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(1645, /* p r */ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, 0x2ab9 _ 0) +NAMED_CHARACTER_REFERENCE(1646, /* p r */ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0, 0x2ab5 _ 0) +NAMED_CHARACTER_REFERENCE(1647, /* p r */ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0, 0x22e8 _ 0) +NAMED_CHARACTER_REFERENCE(1648, /* p r */ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(1649, /* p r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2032 _ 0) +NAMED_CHARACTER_REFERENCE(1650, /* p r */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x2119 _ 0) +NAMED_CHARACTER_REFERENCE(1651, /* p r */ 'n' _ 'E' _ ';', 3, 0, 0x2ab5 _ 0) +NAMED_CHARACTER_REFERENCE(1652, /* p r */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2ab9 _ 0) +NAMED_CHARACTER_REFERENCE(1653, /* p r */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x22e8 _ 0) +NAMED_CHARACTER_REFERENCE(1654, /* p r */ 'o' _ 'd' _ ';', 3, 0, 0x220f _ 0) +NAMED_CHARACTER_REFERENCE(1655, /* p r */ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 7, 0, 0x232e _ 0) +NAMED_CHARACTER_REFERENCE(1656, /* p r */ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0, 0x2312 _ 0) +NAMED_CHARACTER_REFERENCE(1657, /* p r */ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 7, 0, 0x2313 _ 0) +NAMED_CHARACTER_REFERENCE(1658, /* p r */ 'o' _ 'p' _ ';', 3, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(1659, /* p r */ 'o' _ 'p' _ 't' _ 'o' _ ';', 5, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(1660, /* p r */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(1661, /* p r */ 'u' _ 'r' _ 'e' _ 'l' _ ';', 5, 0, 0x22b0 _ 0) +NAMED_CHARACTER_REFERENCE(1662, /* p s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc5) +NAMED_CHARACTER_REFERENCE(1663, /* p s */ 'i' _ ';', 2, 0, 0x03c8 _ 0) +NAMED_CHARACTER_REFERENCE(1664, /* p u */ 'n' _ 'c' _ 's' _ 'p' _ ';', 5, 0, 0x2008 _ 0) +NAMED_CHARACTER_REFERENCE(1665, /* q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2e) +NAMED_CHARACTER_REFERENCE(1666, /* q i */ 'n' _ 't' _ ';', 3, 0, 0x2a0c _ 0) +NAMED_CHARACTER_REFERENCE(1667, /* q o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd62) +NAMED_CHARACTER_REFERENCE(1668, /* q p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2057 _ 0) +NAMED_CHARACTER_REFERENCE(1669, /* q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc6) +NAMED_CHARACTER_REFERENCE(1670, /* q u */ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 10, 0, 0x210d _ 0) +NAMED_CHARACTER_REFERENCE(1671, /* q u */ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 6, 0, 0x2a16 _ 0) +NAMED_CHARACTER_REFERENCE(1672, /* q u */ 'e' _ 's' _ 't' _ ';', 4, 0, 0x003f _ 0) +NAMED_CHARACTER_REFERENCE(1673, /* q u */ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 6, 0, 0x225f _ 0) +NAMED_CHARACTER_REFERENCE(1674, /* q u */ 'o' _ 't', 2, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(1675, /* q u */ 'o' _ 't' _ ';', 3, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(1676, /* r A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21db _ 0) +NAMED_CHARACTER_REFERENCE(1677, /* r A */ 'r' _ 'r' _ ';', 3, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(1678, /* r A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x291c _ 0) +NAMED_CHARACTER_REFERENCE(1679, /* r B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290f _ 0) +NAMED_CHARACTER_REFERENCE(1680, /* r H */ 'a' _ 'r' _ ';', 3, 0, 0x2964 _ 0) +NAMED_CHARACTER_REFERENCE(1681, /* r a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0155 _ 0) +NAMED_CHARACTER_REFERENCE(1682, /* r a */ 'd' _ 'i' _ 'c' _ ';', 4, 0, 0x221a _ 0) +NAMED_CHARACTER_REFERENCE(1683, /* r a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0, 0x29b3 _ 0) +NAMED_CHARACTER_REFERENCE(1684, /* r a */ 'n' _ 'g' _ ';', 3, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(1685, /* r a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2992 _ 0) +NAMED_CHARACTER_REFERENCE(1686, /* r a */ 'n' _ 'g' _ 'e' _ ';', 4, 0, 0x29a5 _ 0) +NAMED_CHARACTER_REFERENCE(1687, /* r a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(1688, /* r a */ 'q' _ 'u' _ 'o', 3, 0, 0x00bb _ 0) +NAMED_CHARACTER_REFERENCE(1689, /* r a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00bb _ 0) +NAMED_CHARACTER_REFERENCE(1690, /* r a */ 'r' _ 'r' _ ';', 3, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1691, /* r a */ 'r' _ 'r' _ 'a' _ 'p' _ ';', 5, 0, 0x2975 _ 0) +NAMED_CHARACTER_REFERENCE(1692, /* r a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e5 _ 0) +NAMED_CHARACTER_REFERENCE(1693, /* r a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0, 0x2920 _ 0) +NAMED_CHARACTER_REFERENCE(1694, /* r a */ 'r' _ 'r' _ 'c' _ ';', 4, 0, 0x2933 _ 0) +NAMED_CHARACTER_REFERENCE(1695, /* r a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0, 0x291e _ 0) +NAMED_CHARACTER_REFERENCE(1696, /* r a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x21aa _ 0) +NAMED_CHARACTER_REFERENCE(1697, /* r a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0, 0x21ac _ 0) +NAMED_CHARACTER_REFERENCE(1698, /* r a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0, 0x2945 _ 0) +NAMED_CHARACTER_REFERENCE(1699, /* r a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2974 _ 0) +NAMED_CHARACTER_REFERENCE(1700, /* r a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, 0x21a3 _ 0) +NAMED_CHARACTER_REFERENCE(1701, /* r a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x219d _ 0) +NAMED_CHARACTER_REFERENCE(1702, /* r a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x291a _ 0) +NAMED_CHARACTER_REFERENCE(1703, /* r a */ 't' _ 'i' _ 'o' _ ';', 4, 0, 0x2236 _ 0) +NAMED_CHARACTER_REFERENCE(1704, /* r a */ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ 's' _ ';', 8, 0, 0x211a _ 0) +NAMED_CHARACTER_REFERENCE(1705, /* r b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290d _ 0) +NAMED_CHARACTER_REFERENCE(1706, /* r b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2773 _ 0) +NAMED_CHARACTER_REFERENCE(1707, /* r b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0, 0x007d _ 0) +NAMED_CHARACTER_REFERENCE(1708, /* r b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0, 0x005d _ 0) +NAMED_CHARACTER_REFERENCE(1709, /* r b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298c _ 0) +NAMED_CHARACTER_REFERENCE(1710, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0, 0x298e _ 0) +NAMED_CHARACTER_REFERENCE(1711, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0, 0x2990 _ 0) +NAMED_CHARACTER_REFERENCE(1712, /* r c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0159 _ 0) +NAMED_CHARACTER_REFERENCE(1713, /* r c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0157 _ 0) +NAMED_CHARACTER_REFERENCE(1714, /* r c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2309 _ 0) +NAMED_CHARACTER_REFERENCE(1715, /* r c */ 'u' _ 'b' _ ';', 3, 0, 0x007d _ 0) +NAMED_CHARACTER_REFERENCE(1716, /* r c */ 'y' _ ';', 2, 0, 0x0440 _ 0) +NAMED_CHARACTER_REFERENCE(1717, /* r d */ 'c' _ 'a' _ ';', 3, 0, 0x2937 _ 0) +NAMED_CHARACTER_REFERENCE(1718, /* r d */ 'l' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2969 _ 0) +NAMED_CHARACTER_REFERENCE(1719, /* r d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(1720, /* r d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(1721, /* r d */ 's' _ 'h' _ ';', 3, 0, 0x21b3 _ 0) +NAMED_CHARACTER_REFERENCE(1722, /* r e */ 'a' _ 'l' _ ';', 3, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(1723, /* r e */ 'a' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0, 0x211b _ 0) +NAMED_CHARACTER_REFERENCE(1724, /* r e */ 'a' _ 'l' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(1725, /* r e */ 'a' _ 'l' _ 's' _ ';', 4, 0, 0x211d _ 0) +NAMED_CHARACTER_REFERENCE(1726, /* r e */ 'c' _ 't' _ ';', 3, 0, 0x25ad _ 0) +NAMED_CHARACTER_REFERENCE(1727, /* r e */ 'g', 1, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(1728, /* r e */ 'g' _ ';', 2, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(1729, /* r f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297d _ 0) +NAMED_CHARACTER_REFERENCE(1730, /* r f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0, 0x230b _ 0) +NAMED_CHARACTER_REFERENCE(1731, /* r f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2f) +NAMED_CHARACTER_REFERENCE(1732, /* r h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(1733, /* r h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(1734, /* r h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0, 0x296c _ 0) +NAMED_CHARACTER_REFERENCE(1735, /* r h */ 'o' _ ';', 2, 0, 0x03c1 _ 0) +NAMED_CHARACTER_REFERENCE(1736, /* r h */ 'o' _ 'v' _ ';', 3, 0, 0x03f1 _ 0) +NAMED_CHARACTER_REFERENCE(1737, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1738, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 13, 0, 0x21a3 _ 0) +NAMED_CHARACTER_REFERENCE(1739, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 15, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(1740, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 13, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(1741, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(1742, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(1743, /* r i */ 'g' _ 'h' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0, 0x21c9 _ 0) +NAMED_CHARACTER_REFERENCE(1744, /* r i */ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x219d _ 0) +NAMED_CHARACTER_REFERENCE(1745, /* r i */ 'g' _ 'h' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 14, 0, 0x22cc _ 0) +NAMED_CHARACTER_REFERENCE(1746, /* r i */ 'n' _ 'g' _ ';', 3, 0, 0x02da _ 0) +NAMED_CHARACTER_REFERENCE(1747, /* r i */ 's' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 11, 0, 0x2253 _ 0) +NAMED_CHARACTER_REFERENCE(1748, /* r l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(1749, /* r l */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(1750, /* r l */ 'm' _ ';', 2, 0, 0x200f _ 0) +NAMED_CHARACTER_REFERENCE(1751, /* r m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0, 0x23b1 _ 0) +NAMED_CHARACTER_REFERENCE(1752, /* r m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0, 0x23b1 _ 0) +NAMED_CHARACTER_REFERENCE(1753, /* r n */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2aee _ 0) +NAMED_CHARACTER_REFERENCE(1754, /* r o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ed _ 0) +NAMED_CHARACTER_REFERENCE(1755, /* r o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fe _ 0) +NAMED_CHARACTER_REFERENCE(1756, /* r o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e7 _ 0) +NAMED_CHARACTER_REFERENCE(1757, /* r o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2986 _ 0) +NAMED_CHARACTER_REFERENCE(1758, /* r o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd63) +NAMED_CHARACTER_REFERENCE(1759, /* r o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a2e _ 0) +NAMED_CHARACTER_REFERENCE(1760, /* r o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0, 0x2a35 _ 0) +NAMED_CHARACTER_REFERENCE(1761, /* r p */ 'a' _ 'r' _ ';', 3, 0, 0x0029 _ 0) +NAMED_CHARACTER_REFERENCE(1762, /* r p */ 'a' _ 'r' _ 'g' _ 't' _ ';', 5, 0, 0x2994 _ 0) +NAMED_CHARACTER_REFERENCE(1763, /* r p */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a12 _ 0) +NAMED_CHARACTER_REFERENCE(1764, /* r r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c9 _ 0) +NAMED_CHARACTER_REFERENCE(1765, /* r s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0, 0x203a _ 0) +NAMED_CHARACTER_REFERENCE(1766, /* r s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc7) +NAMED_CHARACTER_REFERENCE(1767, /* r s */ 'h' _ ';', 2, 0, 0x21b1 _ 0) +NAMED_CHARACTER_REFERENCE(1768, /* r s */ 'q' _ 'b' _ ';', 3, 0, 0x005d _ 0) +NAMED_CHARACTER_REFERENCE(1769, /* r s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(1770, /* r s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(1771, /* r t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0, 0x22cc _ 0) +NAMED_CHARACTER_REFERENCE(1772, /* r t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x22ca _ 0) +NAMED_CHARACTER_REFERENCE(1773, /* r t */ 'r' _ 'i' _ ';', 3, 0, 0x25b9 _ 0) +NAMED_CHARACTER_REFERENCE(1774, /* r t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(1775, /* r t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b8 _ 0) +NAMED_CHARACTER_REFERENCE(1776, /* r t */ 'r' _ 'i' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 7, 0, 0x29ce _ 0) +NAMED_CHARACTER_REFERENCE(1777, /* r u */ 'l' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2968 _ 0) +NAMED_CHARACTER_REFERENCE(1778, /* r x */ ';', 1, 0, 0x211e _ 0) +NAMED_CHARACTER_REFERENCE(1779, /* s a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x015b _ 0) +NAMED_CHARACTER_REFERENCE(1780, /* s b */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201a _ 0) +NAMED_CHARACTER_REFERENCE(1781, /* s c */ ';', 1, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(1782, /* s c */ 'E' _ ';', 2, 0, 0x2ab4 _ 0) +NAMED_CHARACTER_REFERENCE(1783, /* s c */ 'a' _ 'p' _ ';', 3, 0, 0x2ab8 _ 0) +NAMED_CHARACTER_REFERENCE(1784, /* s c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0161 _ 0) +NAMED_CHARACTER_REFERENCE(1785, /* s c */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(1786, /* s c */ 'e' _ ';', 2, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(1787, /* s c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x015f _ 0) +NAMED_CHARACTER_REFERENCE(1788, /* s c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015d _ 0) +NAMED_CHARACTER_REFERENCE(1789, /* s c */ 'n' _ 'E' _ ';', 3, 0, 0x2ab6 _ 0) +NAMED_CHARACTER_REFERENCE(1790, /* s c */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2aba _ 0) +NAMED_CHARACTER_REFERENCE(1791, /* s c */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x22e9 _ 0) +NAMED_CHARACTER_REFERENCE(1792, /* s c */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a13 _ 0) +NAMED_CHARACTER_REFERENCE(1793, /* s c */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(1794, /* s c */ 'y' _ ';', 2, 0, 0x0441 _ 0) +NAMED_CHARACTER_REFERENCE(1795, /* s d */ 'o' _ 't' _ ';', 3, 0, 0x22c5 _ 0) +NAMED_CHARACTER_REFERENCE(1796, /* s d */ 'o' _ 't' _ 'b' _ ';', 4, 0, 0x22a1 _ 0) +NAMED_CHARACTER_REFERENCE(1797, /* s d */ 'o' _ 't' _ 'e' _ ';', 4, 0, 0x2a66 _ 0) +NAMED_CHARACTER_REFERENCE(1798, /* s e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d8 _ 0) +NAMED_CHARACTER_REFERENCE(1799, /* s e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2925 _ 0) +NAMED_CHARACTER_REFERENCE(1800, /* s e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(1801, /* s e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(1802, /* s e */ 'c' _ 't', 2, 0, 0x00a7 _ 0) +NAMED_CHARACTER_REFERENCE(1803, /* s e */ 'c' _ 't' _ ';', 3, 0, 0x00a7 _ 0) +NAMED_CHARACTER_REFERENCE(1804, /* s e */ 'm' _ 'i' _ ';', 3, 0, 0x003b _ 0) +NAMED_CHARACTER_REFERENCE(1805, /* s e */ 's' _ 'w' _ 'a' _ 'r' _ ';', 5, 0, 0x2929 _ 0) +NAMED_CHARACTER_REFERENCE(1806, /* s e */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1807, /* s e */ 't' _ 'm' _ 'n' _ ';', 4, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1808, /* s e */ 'x' _ 't' _ ';', 3, 0, 0x2736 _ 0) +NAMED_CHARACTER_REFERENCE(1809, /* s f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd30) +NAMED_CHARACTER_REFERENCE(1810, /* s f */ 'r' _ 'o' _ 'w' _ 'n' _ ';', 5, 0, 0x2322 _ 0) +NAMED_CHARACTER_REFERENCE(1811, /* s h */ 'a' _ 'r' _ 'p' _ ';', 4, 0, 0x266f _ 0) +NAMED_CHARACTER_REFERENCE(1812, /* s h */ 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0, 0x0449 _ 0) +NAMED_CHARACTER_REFERENCE(1813, /* s h */ 'c' _ 'y' _ ';', 3, 0, 0x0448 _ 0) +NAMED_CHARACTER_REFERENCE(1814, /* s h */ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 7, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1815, /* s h */ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 12, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1816, /* s h */ 'y', 1, 0, 0x00ad _ 0) +NAMED_CHARACTER_REFERENCE(1817, /* s h */ 'y' _ ';', 2, 0, 0x00ad _ 0) +NAMED_CHARACTER_REFERENCE(1818, /* s i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03c3 _ 0) +NAMED_CHARACTER_REFERENCE(1819, /* s i */ 'g' _ 'm' _ 'a' _ 'f' _ ';', 5, 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(1820, /* s i */ 'g' _ 'm' _ 'a' _ 'v' _ ';', 5, 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(1821, /* s i */ 'm' _ ';', 2, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1822, /* s i */ 'm' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a6a _ 0) +NAMED_CHARACTER_REFERENCE(1823, /* s i */ 'm' _ 'e' _ ';', 3, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(1824, /* s i */ 'm' _ 'e' _ 'q' _ ';', 4, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(1825, /* s i */ 'm' _ 'g' _ ';', 3, 0, 0x2a9e _ 0) +NAMED_CHARACTER_REFERENCE(1826, /* s i */ 'm' _ 'g' _ 'E' _ ';', 4, 0, 0x2aa0 _ 0) +NAMED_CHARACTER_REFERENCE(1827, /* s i */ 'm' _ 'l' _ ';', 3, 0, 0x2a9d _ 0) +NAMED_CHARACTER_REFERENCE(1828, /* s i */ 'm' _ 'l' _ 'E' _ ';', 4, 0, 0x2a9f _ 0) +NAMED_CHARACTER_REFERENCE(1829, /* s i */ 'm' _ 'n' _ 'e' _ ';', 4, 0, 0x2246 _ 0) +NAMED_CHARACTER_REFERENCE(1830, /* s i */ 'm' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2a24 _ 0) +NAMED_CHARACTER_REFERENCE(1831, /* s i */ 'm' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x2972 _ 0) +NAMED_CHARACTER_REFERENCE(1832, /* s l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1833, /* s m */ 'a' _ 'l' _ 'l' _ 's' _ 'e' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 12, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1834, /* s m */ 'a' _ 's' _ 'h' _ 'p' _ ';', 5, 0, 0x2a33 _ 0) +NAMED_CHARACTER_REFERENCE(1835, /* s m */ 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0, 0x29e4 _ 0) +NAMED_CHARACTER_REFERENCE(1836, /* s m */ 'i' _ 'd' _ ';', 3, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1837, /* s m */ 'i' _ 'l' _ 'e' _ ';', 4, 0, 0x2323 _ 0) +NAMED_CHARACTER_REFERENCE(1838, /* s m */ 't' _ ';', 2, 0, 0x2aaa _ 0) +NAMED_CHARACTER_REFERENCE(1839, /* s m */ 't' _ 'e' _ ';', 3, 0, 0x2aac _ 0) +NAMED_CHARACTER_REFERENCE(1840, /* s o */ 'f' _ 't' _ 'c' _ 'y' _ ';', 5, 0, 0x044c _ 0) +NAMED_CHARACTER_REFERENCE(1841, /* s o */ 'l' _ ';', 2, 0, 0x002f _ 0) +NAMED_CHARACTER_REFERENCE(1842, /* s o */ 'l' _ 'b' _ ';', 3, 0, 0x29c4 _ 0) +NAMED_CHARACTER_REFERENCE(1843, /* s o */ 'l' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x233f _ 0) +NAMED_CHARACTER_REFERENCE(1844, /* s o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd64) +NAMED_CHARACTER_REFERENCE(1845, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ ';', 5, 0, 0x2660 _ 0) +NAMED_CHARACTER_REFERENCE(1846, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2660 _ 0) +NAMED_CHARACTER_REFERENCE(1847, /* s p */ 'a' _ 'r' _ ';', 3, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1848, /* s q */ 'c' _ 'a' _ 'p' _ ';', 4, 0, 0x2293 _ 0) +NAMED_CHARACTER_REFERENCE(1849, /* s q */ 'c' _ 'u' _ 'p' _ ';', 4, 0, 0x2294 _ 0) +NAMED_CHARACTER_REFERENCE(1850, /* s q */ 's' _ 'u' _ 'b' _ ';', 4, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(1851, /* s q */ 's' _ 'u' _ 'b' _ 'e' _ ';', 5, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(1852, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(1853, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(1854, /* s q */ 's' _ 'u' _ 'p' _ ';', 4, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(1855, /* s q */ 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(1856, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(1857, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(1858, /* s q */ 'u' _ ';', 2, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(1859, /* s q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(1860, /* s q */ 'u' _ 'a' _ 'r' _ 'f' _ ';', 5, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(1861, /* s q */ 'u' _ 'f' _ ';', 3, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(1862, /* s r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1863, /* s s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc8) +NAMED_CHARACTER_REFERENCE(1864, /* s s */ 'e' _ 't' _ 'm' _ 'n' _ ';', 5, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1865, /* s s */ 'm' _ 'i' _ 'l' _ 'e' _ ';', 5, 0, 0x2323 _ 0) +NAMED_CHARACTER_REFERENCE(1866, /* s s */ 't' _ 'a' _ 'r' _ 'f' _ ';', 5, 0, 0x22c6 _ 0) +NAMED_CHARACTER_REFERENCE(1867, /* s t */ 'a' _ 'r' _ ';', 3, 0, 0x2606 _ 0) +NAMED_CHARACTER_REFERENCE(1868, /* s t */ 'a' _ 'r' _ 'f' _ ';', 4, 0, 0x2605 _ 0) +NAMED_CHARACTER_REFERENCE(1869, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 14, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(1870, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'p' _ 'h' _ 'i' _ ';', 10, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(1871, /* s t */ 'r' _ 'n' _ 's' _ ';', 4, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1872, /* s u */ 'b' _ ';', 2, 0, 0x2282 _ 0) +NAMED_CHARACTER_REFERENCE(1873, /* s u */ 'b' _ 'E' _ ';', 3, 0, 0x2ac5 _ 0) +NAMED_CHARACTER_REFERENCE(1874, /* s u */ 'b' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2abd _ 0) +NAMED_CHARACTER_REFERENCE(1875, /* s u */ 'b' _ 'e' _ ';', 3, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(1876, /* s u */ 'b' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2ac3 _ 0) +NAMED_CHARACTER_REFERENCE(1877, /* s u */ 'b' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0, 0x2ac1 _ 0) +NAMED_CHARACTER_REFERENCE(1878, /* s u */ 'b' _ 'n' _ 'E' _ ';', 4, 0, 0x2acb _ 0) +NAMED_CHARACTER_REFERENCE(1879, /* s u */ 'b' _ 'n' _ 'e' _ ';', 4, 0, 0x228a _ 0) +NAMED_CHARACTER_REFERENCE(1880, /* s u */ 'b' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2abf _ 0) +NAMED_CHARACTER_REFERENCE(1881, /* s u */ 'b' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x2979 _ 0) +NAMED_CHARACTER_REFERENCE(1882, /* s u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x2282 _ 0) +NAMED_CHARACTER_REFERENCE(1883, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(1884, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac5 _ 0) +NAMED_CHARACTER_REFERENCE(1885, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228a _ 0) +NAMED_CHARACTER_REFERENCE(1886, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, 0x2acb _ 0) +NAMED_CHARACTER_REFERENCE(1887, /* s u */ 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2ac7 _ 0) +NAMED_CHARACTER_REFERENCE(1888, /* s u */ 'b' _ 's' _ 'u' _ 'b' _ ';', 5, 0, 0x2ad5 _ 0) +NAMED_CHARACTER_REFERENCE(1889, /* s u */ 'b' _ 's' _ 'u' _ 'p' _ ';', 5, 0, 0x2ad3 _ 0) +NAMED_CHARACTER_REFERENCE(1890, /* s u */ 'c' _ 'c' _ ';', 3, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(1891, /* s u */ 'c' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, 0x2ab8 _ 0) +NAMED_CHARACTER_REFERENCE(1892, /* s u */ 'c' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(1893, /* s u */ 'c' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(1894, /* s u */ 'c' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, 0x2aba _ 0) +NAMED_CHARACTER_REFERENCE(1895, /* s u */ 'c' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0, 0x2ab6 _ 0) +NAMED_CHARACTER_REFERENCE(1896, /* s u */ 'c' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0, 0x22e9 _ 0) +NAMED_CHARACTER_REFERENCE(1897, /* s u */ 'c' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(1898, /* s u */ 'm' _ ';', 2, 0, 0x2211 _ 0) +NAMED_CHARACTER_REFERENCE(1899, /* s u */ 'n' _ 'g' _ ';', 3, 0, 0x266a _ 0) +NAMED_CHARACTER_REFERENCE(1900, /* s u */ 'p' _ '1', 2, 0, 0x00b9 _ 0) +NAMED_CHARACTER_REFERENCE(1901, /* s u */ 'p' _ '1' _ ';', 3, 0, 0x00b9 _ 0) +NAMED_CHARACTER_REFERENCE(1902, /* s u */ 'p' _ '2', 2, 0, 0x00b2 _ 0) +NAMED_CHARACTER_REFERENCE(1903, /* s u */ 'p' _ '2' _ ';', 3, 0, 0x00b2 _ 0) +NAMED_CHARACTER_REFERENCE(1904, /* s u */ 'p' _ '3', 2, 0, 0x00b3 _ 0) +NAMED_CHARACTER_REFERENCE(1905, /* s u */ 'p' _ '3' _ ';', 3, 0, 0x00b3 _ 0) +NAMED_CHARACTER_REFERENCE(1906, /* s u */ 'p' _ ';', 2, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(1907, /* s u */ 'p' _ 'E' _ ';', 3, 0, 0x2ac6 _ 0) +NAMED_CHARACTER_REFERENCE(1908, /* s u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2abe _ 0) +NAMED_CHARACTER_REFERENCE(1909, /* s u */ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 6, 0, 0x2ad8 _ 0) +NAMED_CHARACTER_REFERENCE(1910, /* s u */ 'p' _ 'e' _ ';', 3, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(1911, /* s u */ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2ac4 _ 0) +NAMED_CHARACTER_REFERENCE(1912, /* s u */ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 6, 0, 0x27c9 _ 0) +NAMED_CHARACTER_REFERENCE(1913, /* s u */ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 6, 0, 0x2ad7 _ 0) +NAMED_CHARACTER_REFERENCE(1914, /* s u */ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x297b _ 0) +NAMED_CHARACTER_REFERENCE(1915, /* s u */ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0, 0x2ac2 _ 0) +NAMED_CHARACTER_REFERENCE(1916, /* s u */ 'p' _ 'n' _ 'E' _ ';', 4, 0, 0x2acc _ 0) +NAMED_CHARACTER_REFERENCE(1917, /* s u */ 'p' _ 'n' _ 'e' _ ';', 4, 0, 0x228b _ 0) +NAMED_CHARACTER_REFERENCE(1918, /* s u */ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2ac0 _ 0) +NAMED_CHARACTER_REFERENCE(1919, /* s u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(1920, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(1921, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac6 _ 0) +NAMED_CHARACTER_REFERENCE(1922, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228b _ 0) +NAMED_CHARACTER_REFERENCE(1923, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, 0x2acc _ 0) +NAMED_CHARACTER_REFERENCE(1924, /* s u */ 'p' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2ac8 _ 0) +NAMED_CHARACTER_REFERENCE(1925, /* s u */ 'p' _ 's' _ 'u' _ 'b' _ ';', 5, 0, 0x2ad4 _ 0) +NAMED_CHARACTER_REFERENCE(1926, /* s u */ 'p' _ 's' _ 'u' _ 'p' _ ';', 5, 0, 0x2ad6 _ 0) +NAMED_CHARACTER_REFERENCE(1927, /* s w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d9 _ 0) +NAMED_CHARACTER_REFERENCE(1928, /* s w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2926 _ 0) +NAMED_CHARACTER_REFERENCE(1929, /* s w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(1930, /* s w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(1931, /* s w */ 'n' _ 'w' _ 'a' _ 'r' _ ';', 5, 0, 0x292a _ 0) +NAMED_CHARACTER_REFERENCE(1932, /* s z */ 'l' _ 'i' _ 'g', 3, 0, 0x00df _ 0) +NAMED_CHARACTER_REFERENCE(1933, /* s z */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00df _ 0) +NAMED_CHARACTER_REFERENCE(1934, /* t a */ 'r' _ 'g' _ 'e' _ 't' _ ';', 5, 0, 0x2316 _ 0) +NAMED_CHARACTER_REFERENCE(1935, /* t a */ 'u' _ ';', 2, 0, 0x03c4 _ 0) +NAMED_CHARACTER_REFERENCE(1936, /* t b */ 'r' _ 'k' _ ';', 3, 0, 0x23b4 _ 0) +NAMED_CHARACTER_REFERENCE(1937, /* t c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0165 _ 0) +NAMED_CHARACTER_REFERENCE(1938, /* t c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0163 _ 0) +NAMED_CHARACTER_REFERENCE(1939, /* t c */ 'y' _ ';', 2, 0, 0x0442 _ 0) +NAMED_CHARACTER_REFERENCE(1940, /* t d */ 'o' _ 't' _ ';', 3, 0, 0x20db _ 0) +NAMED_CHARACTER_REFERENCE(1941, /* t e */ 'l' _ 'r' _ 'e' _ 'c' _ ';', 5, 0, 0x2315 _ 0) +NAMED_CHARACTER_REFERENCE(1942, /* t f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd31) +NAMED_CHARACTER_REFERENCE(1943, /* t h */ 'e' _ 'r' _ 'e' _ '4' _ ';', 5, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(1944, /* t h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(1945, /* t h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x03b8 _ 0) +NAMED_CHARACTER_REFERENCE(1946, /* t h */ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 7, 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(1947, /* t h */ 'e' _ 't' _ 'a' _ 'v' _ ';', 5, 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(1948, /* t h */ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(1949, /* t h */ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1950, /* t h */ 'i' _ 'n' _ 's' _ 'p' _ ';', 5, 0, 0x2009 _ 0) +NAMED_CHARACTER_REFERENCE(1951, /* t h */ 'k' _ 'a' _ 'p' _ ';', 4, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(1952, /* t h */ 'k' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1953, /* t h */ 'o' _ 'r' _ 'n', 3, 0, 0x00fe _ 0) +NAMED_CHARACTER_REFERENCE(1954, /* t h */ 'o' _ 'r' _ 'n' _ ';', 4, 0, 0x00fe _ 0) +NAMED_CHARACTER_REFERENCE(1955, /* t i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x02dc _ 0) +NAMED_CHARACTER_REFERENCE(1956, /* t i */ 'm' _ 'e' _ 's', 3, 0, 0x00d7 _ 0) +NAMED_CHARACTER_REFERENCE(1957, /* t i */ 'm' _ 'e' _ 's' _ ';', 4, 0, 0x00d7 _ 0) +NAMED_CHARACTER_REFERENCE(1958, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ ';', 5, 0, 0x22a0 _ 0) +NAMED_CHARACTER_REFERENCE(1959, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 7, 0, 0x2a31 _ 0) +NAMED_CHARACTER_REFERENCE(1960, /* t i */ 'm' _ 'e' _ 's' _ 'd' _ ';', 5, 0, 0x2a30 _ 0) +NAMED_CHARACTER_REFERENCE(1961, /* t i */ 'n' _ 't' _ ';', 3, 0, 0x222d _ 0) +NAMED_CHARACTER_REFERENCE(1962, /* t o */ 'e' _ 'a' _ ';', 3, 0, 0x2928 _ 0) +NAMED_CHARACTER_REFERENCE(1963, /* t o */ 'p' _ ';', 2, 0, 0x22a4 _ 0) +NAMED_CHARACTER_REFERENCE(1964, /* t o */ 'p' _ 'b' _ 'o' _ 't' _ ';', 5, 0, 0x2336 _ 0) +NAMED_CHARACTER_REFERENCE(1965, /* t o */ 'p' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, 0x2af1 _ 0) +NAMED_CHARACTER_REFERENCE(1966, /* t o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd65) +NAMED_CHARACTER_REFERENCE(1967, /* t o */ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 6, 0, 0x2ada _ 0) +NAMED_CHARACTER_REFERENCE(1968, /* t o */ 's' _ 'a' _ ';', 3, 0, 0x2929 _ 0) +NAMED_CHARACTER_REFERENCE(1969, /* t p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2034 _ 0) +NAMED_CHARACTER_REFERENCE(1970, /* t r */ 'a' _ 'd' _ 'e' _ ';', 4, 0, 0x2122 _ 0) +NAMED_CHARACTER_REFERENCE(1971, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, 0, 0x25b5 _ 0) +NAMED_CHARACTER_REFERENCE(1972, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 11, 0, 0x25bf _ 0) +NAMED_CHARACTER_REFERENCE(1973, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 11, 0, 0x25c3 _ 0) +NAMED_CHARACTER_REFERENCE(1974, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 13, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(1975, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 8, 0, 0x225c _ 0) +NAMED_CHARACTER_REFERENCE(1976, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 12, 0, 0x25b9 _ 0) +NAMED_CHARACTER_REFERENCE(1977, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 14, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(1978, /* t r */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x25ec _ 0) +NAMED_CHARACTER_REFERENCE(1979, /* t r */ 'i' _ 'e' _ ';', 3, 0, 0x225c _ 0) +NAMED_CHARACTER_REFERENCE(1980, /* t r */ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x2a3a _ 0) +NAMED_CHARACTER_REFERENCE(1981, /* t r */ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2a39 _ 0) +NAMED_CHARACTER_REFERENCE(1982, /* t r */ 'i' _ 's' _ 'b' _ ';', 4, 0, 0x29cd _ 0) +NAMED_CHARACTER_REFERENCE(1983, /* t r */ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 6, 0, 0x2a3b _ 0) +NAMED_CHARACTER_REFERENCE(1984, /* t r */ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 7, 0, 0x23e2 _ 0) +NAMED_CHARACTER_REFERENCE(1985, /* t s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc9) +NAMED_CHARACTER_REFERENCE(1986, /* t s */ 'c' _ 'y' _ ';', 3, 0, 0x0446 _ 0) +NAMED_CHARACTER_REFERENCE(1987, /* t s */ 'h' _ 'c' _ 'y' _ ';', 4, 0, 0x045b _ 0) +NAMED_CHARACTER_REFERENCE(1988, /* t s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0167 _ 0) +NAMED_CHARACTER_REFERENCE(1989, /* t w */ 'i' _ 'x' _ 't' _ ';', 4, 0, 0x226c _ 0) +NAMED_CHARACTER_REFERENCE(1990, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x219e _ 0) +NAMED_CHARACTER_REFERENCE(1991, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0, 0x21a0 _ 0) +NAMED_CHARACTER_REFERENCE(1992, /* u A */ 'r' _ 'r' _ ';', 3, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(1993, /* u H */ 'a' _ 'r' _ ';', 3, 0, 0x2963 _ 0) +NAMED_CHARACTER_REFERENCE(1994, /* u a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fa _ 0) +NAMED_CHARACTER_REFERENCE(1995, /* u a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00fa _ 0) +NAMED_CHARACTER_REFERENCE(1996, /* u a */ 'r' _ 'r' _ ';', 3, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(1997, /* u b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x045e _ 0) +NAMED_CHARACTER_REFERENCE(1998, /* u b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x016d _ 0) +NAMED_CHARACTER_REFERENCE(1999, /* u c */ 'i' _ 'r' _ 'c', 3, 0, 0x00fb _ 0) +NAMED_CHARACTER_REFERENCE(2000, /* u c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00fb _ 0) +NAMED_CHARACTER_REFERENCE(2001, /* u c */ 'y' _ ';', 2, 0, 0x0443 _ 0) +NAMED_CHARACTER_REFERENCE(2002, /* u d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c5 _ 0) +NAMED_CHARACTER_REFERENCE(2003, /* u d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0171 _ 0) +NAMED_CHARACTER_REFERENCE(2004, /* u d */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296e _ 0) +NAMED_CHARACTER_REFERENCE(2005, /* u f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297e _ 0) +NAMED_CHARACTER_REFERENCE(2006, /* u f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd32) +NAMED_CHARACTER_REFERENCE(2007, /* u g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f9 _ 0) +NAMED_CHARACTER_REFERENCE(2008, /* u g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00f9 _ 0) +NAMED_CHARACTER_REFERENCE(2009, /* u h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(2010, /* u h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(2011, /* u h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2580 _ 0) +NAMED_CHARACTER_REFERENCE(2012, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231c _ 0) +NAMED_CHARACTER_REFERENCE(2013, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231c _ 0) +NAMED_CHARACTER_REFERENCE(2014, /* u l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230f _ 0) +NAMED_CHARACTER_REFERENCE(2015, /* u l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f8 _ 0) +NAMED_CHARACTER_REFERENCE(2016, /* u m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016b _ 0) +NAMED_CHARACTER_REFERENCE(2017, /* u m */ 'l', 1, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(2018, /* u m */ 'l' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(2019, /* u o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0173 _ 0) +NAMED_CHARACTER_REFERENCE(2020, /* u o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd66) +NAMED_CHARACTER_REFERENCE(2021, /* u p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(2022, /* u p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(2023, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(2024, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(2025, /* u p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x228e _ 0) +NAMED_CHARACTER_REFERENCE(2026, /* u p */ 's' _ 'i' _ ';', 3, 0, 0x03c5 _ 0) +NAMED_CHARACTER_REFERENCE(2027, /* u p */ 's' _ 'i' _ 'h' _ ';', 4, 0, 0x03d2 _ 0) +NAMED_CHARACTER_REFERENCE(2028, /* u p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x03c5 _ 0) +NAMED_CHARACTER_REFERENCE(2029, /* u p */ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 9, 0, 0x21c8 _ 0) +NAMED_CHARACTER_REFERENCE(2030, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231d _ 0) +NAMED_CHARACTER_REFERENCE(2031, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231d _ 0) +NAMED_CHARACTER_REFERENCE(2032, /* u r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230e _ 0) +NAMED_CHARACTER_REFERENCE(2033, /* u r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016f _ 0) +NAMED_CHARACTER_REFERENCE(2034, /* u r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f9 _ 0) +NAMED_CHARACTER_REFERENCE(2035, /* u s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcca) +NAMED_CHARACTER_REFERENCE(2036, /* u t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f0 _ 0) +NAMED_CHARACTER_REFERENCE(2037, /* u t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0169 _ 0) +NAMED_CHARACTER_REFERENCE(2038, /* u t */ 'r' _ 'i' _ ';', 3, 0, 0x25b5 _ 0) +NAMED_CHARACTER_REFERENCE(2039, /* u t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b4 _ 0) +NAMED_CHARACTER_REFERENCE(2040, /* u u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c8 _ 0) +NAMED_CHARACTER_REFERENCE(2041, /* u u */ 'm' _ 'l', 2, 0, 0x00fc _ 0) +NAMED_CHARACTER_REFERENCE(2042, /* u u */ 'm' _ 'l' _ ';', 3, 0, 0x00fc _ 0) +NAMED_CHARACTER_REFERENCE(2043, /* u w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0, 0x29a7 _ 0) +NAMED_CHARACTER_REFERENCE(2044, /* v A */ 'r' _ 'r' _ ';', 3, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(2045, /* v B */ 'a' _ 'r' _ ';', 3, 0, 0x2ae8 _ 0) +NAMED_CHARACTER_REFERENCE(2046, /* v B */ 'a' _ 'r' _ 'v' _ ';', 4, 0, 0x2ae9 _ 0) +NAMED_CHARACTER_REFERENCE(2047, /* v D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a8 _ 0) +NAMED_CHARACTER_REFERENCE(2048, /* v a */ 'n' _ 'g' _ 'r' _ 't' _ ';', 5, 0, 0x299c _ 0) +NAMED_CHARACTER_REFERENCE(2049, /* v a */ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 9, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(2050, /* v a */ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 7, 0, 0x03f0 _ 0) +NAMED_CHARACTER_REFERENCE(2051, /* v a */ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 9, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(2052, /* v a */ 'r' _ 'p' _ 'h' _ 'i' _ ';', 5, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(2053, /* v a */ 'r' _ 'p' _ 'i' _ ';', 4, 0, 0x03d6 _ 0) +NAMED_CHARACTER_REFERENCE(2054, /* v a */ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 8, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(2055, /* v a */ 'r' _ 'r' _ ';', 3, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(2056, /* v a */ 'r' _ 'r' _ 'h' _ 'o' _ ';', 5, 0, 0x03f1 _ 0) +NAMED_CHARACTER_REFERENCE(2057, /* v a */ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 7, 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(2058, /* v a */ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 7, 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(2059, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(2060, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(2061, /* v c */ 'y' _ ';', 2, 0, 0x0432 _ 0) +NAMED_CHARACTER_REFERENCE(2062, /* v d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a2 _ 0) +NAMED_CHARACTER_REFERENCE(2063, /* v e */ 'e' _ ';', 2, 0, 0x2228 _ 0) +NAMED_CHARACTER_REFERENCE(2064, /* v e */ 'e' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x22bb _ 0) +NAMED_CHARACTER_REFERENCE(2065, /* v e */ 'e' _ 'e' _ 'q' _ ';', 4, 0, 0x225a _ 0) +NAMED_CHARACTER_REFERENCE(2066, /* v e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0, 0x22ee _ 0) +NAMED_CHARACTER_REFERENCE(2067, /* v e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(2068, /* v e */ 'r' _ 't' _ ';', 3, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(2069, /* v f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd33) +NAMED_CHARACTER_REFERENCE(2070, /* v l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(2071, /* v o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd67) +NAMED_CHARACTER_REFERENCE(2072, /* v p */ 'r' _ 'o' _ 'p' _ ';', 4, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(2073, /* v r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(2074, /* v s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccb) +NAMED_CHARACTER_REFERENCE(2075, /* v z */ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 6, 0, 0x299a _ 0) +NAMED_CHARACTER_REFERENCE(2076, /* w c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0175 _ 0) +NAMED_CHARACTER_REFERENCE(2077, /* w e */ 'd' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x2a5f _ 0) +NAMED_CHARACTER_REFERENCE(2078, /* w e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x2227 _ 0) +NAMED_CHARACTER_REFERENCE(2079, /* w e */ 'd' _ 'g' _ 'e' _ 'q' _ ';', 5, 0, 0x2259 _ 0) +NAMED_CHARACTER_REFERENCE(2080, /* w e */ 'i' _ 'e' _ 'r' _ 'p' _ ';', 5, 0, 0x2118 _ 0) +NAMED_CHARACTER_REFERENCE(2081, /* w f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd34) +NAMED_CHARACTER_REFERENCE(2082, /* w o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd68) +NAMED_CHARACTER_REFERENCE(2083, /* w p */ ';', 1, 0, 0x2118 _ 0) +NAMED_CHARACTER_REFERENCE(2084, /* w r */ ';', 1, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(2085, /* w r */ 'e' _ 'a' _ 't' _ 'h' _ ';', 5, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(2086, /* w s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccc) +NAMED_CHARACTER_REFERENCE(2087, /* x c */ 'a' _ 'p' _ ';', 3, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(2088, /* x c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x25ef _ 0) +NAMED_CHARACTER_REFERENCE(2089, /* x c */ 'u' _ 'p' _ ';', 3, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(2090, /* x d */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25bd _ 0) +NAMED_CHARACTER_REFERENCE(2091, /* x f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd35) +NAMED_CHARACTER_REFERENCE(2092, /* x h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(2093, /* x h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(2094, /* x i */ ';', 1, 0, 0x03be _ 0) +NAMED_CHARACTER_REFERENCE(2095, /* x l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(2096, /* x l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(2097, /* x m */ 'a' _ 'p' _ ';', 3, 0, 0x27fc _ 0) +NAMED_CHARACTER_REFERENCE(2098, /* x n */ 'i' _ 's' _ ';', 3, 0, 0x22fb _ 0) +NAMED_CHARACTER_REFERENCE(2099, /* x o */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2a00 _ 0) +NAMED_CHARACTER_REFERENCE(2100, /* x o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd69) +NAMED_CHARACTER_REFERENCE(2101, /* x o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a01 _ 0) +NAMED_CHARACTER_REFERENCE(2102, /* x o */ 't' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2a02 _ 0) +NAMED_CHARACTER_REFERENCE(2103, /* x r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(2104, /* x r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(2105, /* x s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccd) +NAMED_CHARACTER_REFERENCE(2106, /* x s */ 'q' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x2a06 _ 0) +NAMED_CHARACTER_REFERENCE(2107, /* x u */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a04 _ 0) +NAMED_CHARACTER_REFERENCE(2108, /* x u */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25b3 _ 0) +NAMED_CHARACTER_REFERENCE(2109, /* x v */ 'e' _ 'e' _ ';', 3, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(2110, /* x w */ 'e' _ 'd' _ 'g' _ 'e' _ ';', 5, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(2111, /* y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fd _ 0) +NAMED_CHARACTER_REFERENCE(2112, /* y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00fd _ 0) +NAMED_CHARACTER_REFERENCE(2113, /* y a */ 'c' _ 'y' _ ';', 3, 0, 0x044f _ 0) +NAMED_CHARACTER_REFERENCE(2114, /* y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0177 _ 0) +NAMED_CHARACTER_REFERENCE(2115, /* y c */ 'y' _ ';', 2, 0, 0x044b _ 0) +NAMED_CHARACTER_REFERENCE(2116, /* y e */ 'n', 1, 0, 0x00a5 _ 0) +NAMED_CHARACTER_REFERENCE(2117, /* y e */ 'n' _ ';', 2, 0, 0x00a5 _ 0) +NAMED_CHARACTER_REFERENCE(2118, /* y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd36) +NAMED_CHARACTER_REFERENCE(2119, /* y i */ 'c' _ 'y' _ ';', 3, 0, 0x0457 _ 0) +NAMED_CHARACTER_REFERENCE(2120, /* y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6a) +NAMED_CHARACTER_REFERENCE(2121, /* y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcce) +NAMED_CHARACTER_REFERENCE(2122, /* y u */ 'c' _ 'y' _ ';', 3, 0, 0x044e _ 0) +NAMED_CHARACTER_REFERENCE(2123, /* y u */ 'm' _ 'l', 2, 0, 0x00ff _ 0) +NAMED_CHARACTER_REFERENCE(2124, /* y u */ 'm' _ 'l' _ ';', 3, 0, 0x00ff _ 0) +NAMED_CHARACTER_REFERENCE(2125, /* z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x017a _ 0) +NAMED_CHARACTER_REFERENCE(2126, /* z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x017e _ 0) +NAMED_CHARACTER_REFERENCE(2127, /* z c */ 'y' _ ';', 2, 0, 0x0437 _ 0) +NAMED_CHARACTER_REFERENCE(2128, /* z d */ 'o' _ 't' _ ';', 3, 0, 0x017c _ 0) +NAMED_CHARACTER_REFERENCE(2129, /* z e */ 'e' _ 't' _ 'r' _ 'f' _ ';', 5, 0, 0x2128 _ 0) +NAMED_CHARACTER_REFERENCE(2130, /* z e */ 't' _ 'a' _ ';', 3, 0, 0x03b6 _ 0) +NAMED_CHARACTER_REFERENCE(2131, /* z f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd37) +NAMED_CHARACTER_REFERENCE(2132, /* z h */ 'c' _ 'y' _ ';', 3, 0, 0x0436 _ 0) +NAMED_CHARACTER_REFERENCE(2133, /* z i */ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x21dd _ 0) +NAMED_CHARACTER_REFERENCE(2134, /* z o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6b) +NAMED_CHARACTER_REFERENCE(2135, /* z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccf) +NAMED_CHARACTER_REFERENCE(2136, /* z w */ 'j' _ ';', 2, 0, 0x200d _ 0) +NAMED_CHARACTER_REFERENCE(2137, /* z w */ 'n' _ 'j' _ ';', 3, 0, 0x200c _ 0) #undef _ diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index 4dcfbb855cac..d27eb89ad054 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -433,6 +433,16 @@ function do_register_cleanup(aFunction) * @return nsILocalFile of the profile directory. */ function do_get_profile() { + // Since we have a profile, we will notify profile shutdown topics at + // the end of the current test, to ensure correct cleanup on shutdown. + do_register_cleanup(function() { + let obsSvc = Components.classes["@mozilla.org/observer-service;1"]. + getService(Components.interfaces.nsIObserverService); + obsSvc.notifyObservers(null, "profile-change-net-teardown", null); + obsSvc.notifyObservers(null, "profile-change-teardown", null); + obsSvc.notifyObservers(null, "profile-before-change", null); + }); + let env = Components.classes["@mozilla.org/process/environment;1"] .getService(Components.interfaces.nsIEnvironment); // the python harness sets this in the environment for us @@ -452,7 +462,7 @@ function do_get_profile() { throw Components.results.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIDirectoryProvider) || + if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) || iid.equals(Components.interfaces.nsISupports)) { return this; } diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index a9db3e727343..104e0e96ac70 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -38,7 +38,7 @@ # # ***** END LICENSE BLOCK ***** */ -import re, sys, os, os.path, logging, shutil, signal +import re, sys, os, os.path, logging, shutil, signal, math from glob import glob from optparse import OptionParser from subprocess import Popen, PIPE, STDOUT @@ -57,24 +57,73 @@ class XPCShellTests(object): self.log.setLevel(logging.INFO) self.log.addHandler(handler) - def readManifest(self, manifest): + def readManifest(self): """ - Given a manifest file containing a list of test directories, - return a list of absolute paths to the directories contained within. + For a given manifest file, read the contents and populate self.testdirs """ - manifestdir = os.path.dirname(manifest) - testdirs = [] + manifestdir = os.path.dirname(self.manifest) try: - f = open(manifest, "r") + f = open(self.manifest, "r") for line in f: - dir = line.rstrip() - path = os.path.join(manifestdir, dir) + path = os.path.join(manifestdir, line.rstrip()) if os.path.isdir(path): - testdirs.append(path) + self.testdirs.append(path) f.close() except: pass # just eat exceptions - return testdirs + + def buildTestList(self): + """ + Builds a dict of {"testdir" : ["testfile1", "testfile2", ...], "testdir2"...}. + If manifest is given override testdirs to build initial list of directories and tests. + If testpath is given, use that, otherwise chunk if requested. + The resulting set of tests end up in self.alltests + """ + self.buildTestPath() + + self.alltests = {} + if self.manifest is not None: + self.readManifest() + + for dir in self.testdirs: + tests = self.getTestFiles(dir) + if tests: + self.alltests[os.path.abspath(dir)] = tests + + if self.singleFile is None and self.totalChunks > 1: + self.chunkTests() + + def chunkTests(self): + """ + Split the list of tests up into [totalChunks] pieces and filter the + self.alltests based on thisChunk, so we only run a subset. + """ + totalTests = 0 + for dir in self.alltests: + totalTests += len(self.alltests[dir]) + + testsPerChunk = math.ceil(totalTests / float(self.totalChunks)) + start = int(round((self.thisChunk-1) * testsPerChunk)) + end = start + testsPerChunk + currentCount = 0 + + templist = {} + for dir in self.alltests: + startPosition = 0 + dirCount = len(self.alltests[dir]) + endPosition = dirCount + if currentCount < start and currentCount + dirCount >= start: + startPosition = int(start - currentCount) + if currentCount + dirCount > end: + endPosition = int(end - currentCount) + if end - currentCount < 0 or (currentCount + dirCount < start): + endPosition = 0 + + if startPosition is not endPosition: + templist[dir] = self.alltests[dir][startPosition:endPosition] + currentCount += dirCount + + self.alltests = templist def setAbsPath(self): """ @@ -167,7 +216,7 @@ class XPCShellTests(object): |singleFile| will be the optional test only, or |None|. """ self.singleFile = None - if self.testPath: + if self.testPath is not None: if self.testPath.endswith('.js'): # Split into path and file. if self.testPath.find('/') == -1: @@ -209,10 +258,10 @@ class XPCShellTests(object): On a remote system, this is overloaded to find files in the remote directory structure. """ - testfiles = sorted(glob(os.path.join(testdir, "test_*.js"))) + testfiles = sorted(glob(os.path.join(os.path.abspath(testdir), "test_*.js"))) if self.singleFile: if self.singleFile in [os.path.basename(x) for x in testfiles]: - testfiles = [os.path.join(testdir, self.singleFile)] + testfiles = [os.path.abspath(os.path.join(testdir, self.singleFile))] else: # not in this dir? skip it return None @@ -313,7 +362,8 @@ class XPCShellTests(object): def runTests(self, xpcshell, xrePath=None, symbolsPath=None, manifest=None, testdirs=[], testPath=None, interactive=False, logfiles=True, - debuggerInfo=None): + thisChunk=1, totalChunks=1, debugger=None, + debuggerArgs=None, debuggerInteractive=False): """Run xpcshell tests. |xpcshell|, is the xpcshell executable to use to run the tests. @@ -341,7 +391,9 @@ class XPCShellTests(object): self.testPath = testPath self.interactive = interactive self.logfiles = logfiles - self.debuggerInfo = debuggerInfo + self.totalChunks = totalChunks + self.thisChunk = thisChunk + self.debuggerInfo = getDebuggerInfo(self.oldcwd, debugger, debuggerArgs, debuggerInteractive) if not testdirs and not manifest: # nothing to test! @@ -356,39 +408,26 @@ class XPCShellTests(object): self.buildEnvironment() pStdout, pStderr = self.getPipes() - # Override testdirs. - if manifest is not None: - testdirs = self.readManifest(os.path.abspath(manifest)) - - self.buildTestPath() - - # Process each test directory individually. - for testdir in testdirs: - self.buildXpcsCmd(testdir) + self.buildTestList() + for testdir in sorted(self.alltests.keys()): if self.testPath and not testdir.endswith(self.testPath): continue - testdir = os.path.abspath(testdir) - + self.buildXpcsCmd(testdir) testHeadFiles = self.getHeadFiles(testdir) testTailFiles = self.getTailFiles(testdir) - - testfiles = self.getTestFiles(testdir) - if testfiles == None: - continue - cmdH = self.buildCmdHead(testHeadFiles, testTailFiles, self.xpcsCmd) # Now execute each test individually. - for test in testfiles: + for test in self.alltests[testdir]: # create a temp dir that the JS harness can stick a profile in self.profileDir = self.setupProfileDir() self.leakLogFile = self.setupLeakLogging() # The test file will have to be loaded after the head files. cmdT = ['-e', 'const _TEST_FILE = ["%s"];' % - replaceBackSlashes(os.path.join(testdir, test))] + replaceBackSlashes(test)] try: proc = self.launchProcess(cmdH + cmdT + self.xpcsRunArgs, @@ -455,6 +494,12 @@ class XPCShellOptions(OptionParser): self.add_option("--test-path", type="string", dest="testPath", default=None, help="single path and/or test filename to test") + self.add_option("--total-chunks", + type = "int", dest = "totalChunks", default=1, + help = "how many chunks to split the tests up into") + self.add_option("--this-chunk", + type = "int", dest = "thisChunk", default=1, + help = "which chunk to run between 1 and --total-chunks") def main(): parser = XPCShellOptions() @@ -468,23 +513,12 @@ def main(): sys.exit(1) xpcsh = XPCShellTests() - debuggerInfo = getDebuggerInfo(xpcsh.oldcwd, options.debugger, options.debuggerArgs, - options.debuggerInteractive); if options.interactive and not options.testPath: print >>sys.stderr, "Error: You must specify a test filename in interactive mode!" sys.exit(1) - - if not xpcsh.runTests(args[0], - xrePath=options.xrePath, - symbolsPath=options.symbolsPath, - manifest=options.manifest, - testdirs=args[1:], - testPath=options.testPath, - interactive=options.interactive, - logfiles=options.logfiles, - debuggerInfo=debuggerInfo): + if not xpcsh.runTests(args[0], testdirs=args[1:], **options.__dict__): sys.exit(1) if __name__ == '__main__': diff --git a/toolkit/components/downloads/test/browser/browser_bug414214.js b/toolkit/components/downloads/test/browser/browser_bug414214.js index f9ab87f2ae3d..93b34a11c58e 100644 --- a/toolkit/components/downloads/test/browser/browser_bug414214.js +++ b/toolkit/components/downloads/test/browser/browser_bug414214.js @@ -46,23 +46,17 @@ function test() db.executeSimpleSQL("DELETE FROM moz_downloads"); // See if the DM is already open, and if it is, close it! - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - var win = wm.getMostRecentWindow("Download:Manager"); + var win = Services.wm.getMostRecentWindow("Download:Manager"); if (win) win.close(); // We need to set browser.download.manager.closeWhenDone to true to test this - Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch). - setBoolPref(PREF_BDM_CLOSEWHENDONE, true); - - var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); + Services.prefs.setBoolPref(PREF_BDM_CLOSEWHENDONE, true); // register a callback to add a load listener to know when the download // manager opens - ww.registerNotification(function (aSubject, aTopic, aData) { - ww.unregisterNotification(arguments.callee); + Services.ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.unregisterNotification(arguments.callee); var win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("DOMContentLoaded", finishUp, false); @@ -76,8 +70,7 @@ function test() // Reset the pref to its default value try { - Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch). - clearUserPref(PREF_BDM_CLOSEWHENDONE); + Services.prefs.clearUserPref(PREF_BDM_CLOSEWHENDONE); } catch (err) { } diff --git a/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js b/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js index 1edaea808a6d..bdc557e9d12d 100644 --- a/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js +++ b/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js @@ -105,9 +105,7 @@ function test() db.executeSimpleSQL("DELETE FROM moz_downloads"); // See if the DM is already open, and if it is, close it! - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - var win = wm.getMostRecentWindow("Download:Manager"); + var win = Services.wm.getMostRecentWindow("Download:Manager"); if (win) win.close(); @@ -117,7 +115,7 @@ function test() // The window doesn't open once we call show, so we need to wait a little bit function finishUp() { - var win = wm.getMostRecentWindow("Download:Manager"); + var win = Services.wm.getMostRecentWindow("Download:Manager"); // Now we can run our tests for each (var t in testFuncs) diff --git a/toolkit/components/downloads/test/unit/head_download_manager.js b/toolkit/components/downloads/test/unit/head_download_manager.js index 4d7d421e1ad3..8f9b7eea5c28 100644 --- a/toolkit/components/downloads/test/unit/head_download_manager.js +++ b/toolkit/components/downloads/test/unit/head_download_manager.js @@ -63,7 +63,7 @@ var provider = { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js b/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js index a49ffeba923b..ecdccce9f053 100644 --- a/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js +++ b/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js @@ -89,10 +89,6 @@ function test() { pwmgr.addLogin(new nsLoginInfo(urls[i], urls[i], null, users[i], pwds[i], "u"+(i+1), "p"+(i+1))); - // Detect when the password manager window is opened - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - // Open the password manager dialog const PWMGR_DLG = "chrome://passwordmgr/content/passwordManager.xul"; let pwmgrdlg = window.openDialog(PWMGR_DLG, "Toolkit:PasswordManager", ""); @@ -115,9 +111,9 @@ function test() { // only watch for a confirmation dialog every other time being called if (showMode) { - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { if (aTopic == "domwindowclosed") - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); else if (aTopic == "domwindowopened") { let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); SimpleTest.waitForFocus(function() { @@ -127,11 +123,9 @@ function test() { }); } - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { + Services.obs.addObserver(function (aSubject, aTopic, aData) { if (aTopic == "passwordmgr-password-toggle-complete") { - obsSvc.removeObserver(arguments.callee, aTopic, false); + Services.obs.removeObserver(arguments.callee, aTopic, false); func(); } }, "passwordmgr-password-toggle-complete", false); @@ -234,9 +228,9 @@ function test() { checkColumnEntries(2, expectedValues); checkSortDirection(passwordCol, true); // cleanup - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { // unregister ourself - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); pwmgr.removeAllLogins(); finish(); diff --git a/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js b/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js index 5c6db7d89409..4d1c0e7d63d8 100644 --- a/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js +++ b/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js @@ -74,10 +74,6 @@ function test() { ]; logins.forEach(function (login) pwmgr.addLogin(login)); - // Detect when the password manager window is opened - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - // Open the password manager dialog const PWMGR_DLG = "chrome://passwordmgr/content/passwordManager.xul"; let pwmgrdlg = window.openDialog(PWMGR_DLG, "Toolkit:PasswordManager", ""); @@ -125,9 +121,9 @@ function test() { // only watch for a confirmation dialog every other time being called if (showMode) { - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { if (aTopic == "domwindowclosed") - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); else if (aTopic == "domwindowopened") { let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); SimpleTest.waitForFocus(function() { @@ -137,11 +133,9 @@ function test() { }); } - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { + Services.obs.addObserver(function (aSubject, aTopic, aData) { if (aTopic == "passwordmgr-password-toggle-complete") { - obsSvc.removeObserver(arguments.callee, aTopic, false); + Services.obs.removeObserver(arguments.callee, aTopic, false); func(); } }, "passwordmgr-password-toggle-complete", false); @@ -219,9 +213,9 @@ function test() { function lastStep() { // cleanup - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { // unregister ourself - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); pwmgr.removeAllLogins(); finish(); diff --git a/toolkit/components/places/src/utils.js b/toolkit/components/places/src/utils.js index 6dcce29100d1..46e718489cb1 100644 --- a/toolkit/components/places/src/utils.js +++ b/toolkit/components/places/src/utils.js @@ -40,10 +40,6 @@ * * ***** END LICENSE BLOCK ***** */ -function LOG(str) { - dump("*** " + str + "\n"); -} - var EXPORTED_SYMBOLS = ["PlacesUtils"]; var Ci = Components.interfaces; @@ -52,6 +48,8 @@ var Cr = Components.results; var Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); const EXCLUDE_FROM_BACKUP_ANNO = "places/excludeFromBackup"; const POST_DATA_ANNO = "bookmarkProperties/POSTData"; @@ -106,66 +104,6 @@ var PlacesUtils = { // Place entries as raw URL text TYPE_UNICODE: "text/unicode", - /** - * The Bookmarks Service. - */ - get bookmarks() { - delete this.bookmarks; - return this.bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - }, - - /** - * The Nav History Service. - */ - get history() { - delete this.history; - return this.history = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - }, - - /** - * The Live Bookmark Service. - */ - get livemarks() { - delete this.livemarks; - return this.livemarks = Cc["@mozilla.org/browser/livemark-service;2"]. - getService(Ci.nsILivemarkService); - }, - - /** - * The Annotations Service. - */ - get annotations() { - delete this.annotations; - return this.annotations = Cc["@mozilla.org/browser/annotation-service;1"]. - getService(Ci.nsIAnnotationService); - }, - - /** - * The Favicons Service - */ - get favicons() { - delete this.favicons; - return this.favicons = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); - }, - - /** - * The Places Tagging Service - */ - get tagging() { - delete this.tagging; - return this.tagging = Cc["@mozilla.org/browser/tagging-service;1"]. - getService(Ci.nsITaggingService); - }, - - get observerSvc() { - delete this.observerSvc; - return this.observerSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - }, - /** * Makes a URI from a spec. * @param aSpec @@ -173,21 +111,7 @@ var PlacesUtils = { * @returns A URI object for the spec. */ _uri: function PU__uri(aSpec) { - return Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService). - newURI(aSpec, null, null); - }, - - /** - * String bundle helpers - */ - get _bundle() { - const PLACES_STRING_BUNDLE_URI = - "chrome://places/locale/places.properties"; - delete this._bundle; - return this._bundle = Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService). - createBundle(PLACES_STRING_BUNDLE_URI); + return NetUtil.newURI(aSpec); }, getFormattedString: function PU_getFormattedString(key, params) { @@ -298,7 +222,7 @@ var PlacesUtils = { this.annotations.addObserver(this, false); // observe shutdown, so we can remove the anno observer - this.observerSvc.addObserver(this, "xpcom-shutdown", false); + Services.obs.addObserver(this, "xpcom-shutdown", false); var readOnly = this.annotations.getItemsWithAnnotation(READ_ONLY_ANNO); this.__defineGetter__("_readOnly", function() readOnly); @@ -312,7 +236,7 @@ var PlacesUtils = { observe: function PU_observe(aSubject, aTopic, aData) { if (aTopic == "xpcom-shutdown") { this.annotations.removeObserver(this); - this.observerSvc.removeObserver(this, "xpcom-shutdown"); + Services.obs.removeObserver(this, "xpcom-shutdown"); } }, @@ -717,7 +641,6 @@ var PlacesUtils = { } break; default: - LOG("Cannot unwrap data of type " + type); throw Cr.NS_ERROR_INVALID_ARG; } return nodes; @@ -1495,9 +1418,7 @@ var PlacesUtils = { } return true; }); - } catch(ex) { - LOG(ex); - } + } catch(ex) {} if (annos.length != 0) aJSNode.annos = annos; } @@ -1682,9 +1603,9 @@ var PlacesUtils = { restoreBookmarksFromJSONFile: function PU_restoreBookmarksFromJSONFile(aFile) { let failed = false; - this.observerSvc.notifyObservers(null, - RESTORE_BEGIN_NSIOBSERVER_TOPIC, - RESTORE_NSIOBSERVER_DATA); + Services.obs.notifyObservers(null, + RESTORE_BEGIN_NSIOBSERVER_TOPIC, + RESTORE_NSIOBSERVER_DATA); try { // open file stream @@ -1710,17 +1631,17 @@ var PlacesUtils = { } catch (exc) { failed = true; - this.observerSvc.notifyObservers(null, - RESTORE_FAILED_NSIOBSERVER_TOPIC, - RESTORE_NSIOBSERVER_DATA); + Services.obs.notifyObservers(null, + RESTORE_FAILED_NSIOBSERVER_TOPIC, + RESTORE_NSIOBSERVER_DATA); Cu.reportError("Bookmarks JSON restore failed: " + exc); throw exc; } finally { if (!failed) { - this.observerSvc.notifyObservers(null, - RESTORE_SUCCESS_NSIOBSERVER_TOPIC, - RESTORE_NSIOBSERVER_DATA); + Services.obs.notifyObservers(null, + RESTORE_SUCCESS_NSIOBSERVER_TOPIC, + RESTORE_NSIOBSERVER_DATA); } } }, @@ -1763,9 +1684,7 @@ var PlacesUtils = { }, get folder() { - let dirSvc = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); - let bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsILocalFile); + let bookmarksBackupDir = Services.dirsvc.get("ProfD", Ci.nsILocalFile); bookmarksBackupDir.append("bookmarkbackups"); if (!bookmarksBackupDir.exists()) { bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700); @@ -2014,3 +1933,46 @@ var PlacesUtils = { Cu.import("resource://gre/modules/PlacesDBUtils.jsm"); } }; + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "history", + "@mozilla.org/browser/nav-history-service;1", + "nsINavHistoryService"); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "bhistory", function() { + return PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory); +}); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "ghistory2", function() { + return PlacesUtils.history.QueryInterface(Ci.nsIGlobalHistory2); +}); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "ghistory3", function() { + return PlacesUtils.history.QueryInterface(Ci.nsIGlobalHistory3); +}); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "favicons", + "@mozilla.org/browser/favicon-service;1", + "nsIFaviconService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "bookmarks", + "@mozilla.org/browser/nav-bookmarks-service;1", + "nsINavBookmarksService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "annotations", + "@mozilla.org/browser/annotation-service;1", + "nsIAnnotationService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "tagging", + "@mozilla.org/browser/tagging-service;1", + "nsITaggingService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "livemarks", + "@mozilla.org/browser/livemark-service;2", + "nsILivemarkService"); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "_bundle", function() { + const PLACES_STRING_BUNDLE_URI = "chrome://places/locale/places.properties"; + return Cc["@mozilla.org/intl/stringbundle;1"]. + getService(Ci.nsIStringBundleService). + createBundle(PLACES_STRING_BUNDLE_URI); +}); diff --git a/toolkit/components/places/tests/Makefile.in b/toolkit/components/places/tests/Makefile.in index 51db1fe4b8d8..894be665c7aa 100644 --- a/toolkit/components/places/tests/Makefile.in +++ b/toolkit/components/places/tests/Makefile.in @@ -56,6 +56,11 @@ XPCSHELL_TESTS = \ network \ $(NULL) +# Files in the main "tests" folder. +XPCSHELL_TESTS_COMMON = \ + head_common.js \ + $(NULL) + # Simple MochiTests MOCHI_TESTS = \ mochitest/test_bug_411966.html \ @@ -77,3 +82,6 @@ include $(topsrcdir)/config/rules.mk libs:: $(MOCHI_TESTS) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) + +libs:: $(XPCSHELL_TESTS_COMMON) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/xpcshell/$(MODULE) diff --git a/toolkit/components/places/tests/autocomplete/head_000.js b/toolkit/components/places/tests/autocomplete/head_000.js deleted file mode 100644 index 11c2f66ba3c7..000000000000 --- a/toolkit/components/places/tests/autocomplete/head_000.js +++ /dev/null @@ -1,141 +0,0 @@ -/* ***** 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 Places. - * - * The Initial Developer of the Original Code is - * Google Inc. - * Portions created by the Initial Developer are Copyright (C) 2005 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brian Ryner - * Dietrich Ayala - * - * Alternatively, the contents of this file may be used under the terms of - * either 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 ***** */ - -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cr = Components.results; - -var profDir = do_get_profile(); - -let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -let provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - let histFile = profDir.clone(); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -// Delete a previously created sqlite file -function clearDB() { - try { - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} diff --git a/toolkit/components/places/tests/autocomplete/head_autocomplete.js b/toolkit/components/places/tests/autocomplete/head_autocomplete.js index a2607e70a4c4..db3209d5a063 100644 --- a/toolkit/components/places/tests/autocomplete/head_autocomplete.js +++ b/toolkit/components/places/tests/autocomplete/head_autocomplete.js @@ -35,22 +35,27 @@ * * ***** END LICENSE BLOCK ***** */ +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + + /** * Header file for autocomplete testcases that create a set of pages with uris, * titles, tags and tests that a given search term matches certain pages. */ -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); - -const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK; -const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED; -const TRANSITION_BOOKMARK = Ci.nsINavHistoryService.TRANSITION_BOOKMARK; -const TRANSITION_EMBED = Ci.nsINavHistoryService.TRANSITION_EMBED; -const TRANSITION_FRAMED_LINK = Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK; -const TRANSITION_REDIRECT_PERMANENT = Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT; -const TRANSITION_REDIRECT_TEMPORARY = Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY; -const TRANSITION_DOWNLOAD = Ci.nsINavHistoryService.TRANSITION_DOWNLOAD; - let current_test = 0; function AutoCompleteInput(aSearches) { @@ -72,12 +77,14 @@ AutoCompleteInput.prototype = { setSelectedIndex: function() {}, get searchCount() { return this.searches.length; }, getSearchAt: function(aIndex) this.searches[aIndex], - QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteInput, Ci.nsIAutoCompletePopup]) + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIAutoCompleteInput, + Ci.nsIAutoCompletePopup, + ]) }; -function toURI(aSpec) -{ - return iosvc.newURI(aSpec, null, null); +function toURI(aSpec) { + return uri(aSpec); } let appendTags = true; @@ -188,72 +195,6 @@ let gDate = new Date(Date.now() - 1000 * 60 * 60) * 1000; // Store the page info for each uri let gPages = []; -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Sets title synchronously for a page in moz_places synchronously. - * History.SetPageTitle uses LAZY_ADD so we can't rely on it. - * - * @param aURI - * An nsIURI to set the title for. - * @param aTitle - * The title to set the page to. - * @throws if the page is not found in the database. - * - * @note this function only exists because we have no API to do this. It should - * be added in bug 421897. - */ -function setPageTitle(aURI, aTitle) { - let dbConn = DBConn(); - // Check that the page exists. - let stmt = dbConn.createStatement( - "SELECT id FROM moz_places_view WHERE url = :url"); - stmt.params.url = aURI.spec; - try { - if (!stmt.executeStep()) { - do_throw("Unable to find page " + aURIString); - return; - } - } - finally { - stmt.finalize(); - } - - // Update the title - stmt = dbConn.createStatement( - "UPDATE moz_places_view SET title = :title WHERE url = :url"); - stmt.params.title = aTitle; - stmt.params.url = aURI.spec; - try { - stmt.execute(); - } - finally { - stmt.finalize(); - } -} /** * Adds a livemark container with a single child, and creates various properties diff --git a/toolkit/components/places/tests/bookmarks/head_bookmarks.js b/toolkit/components/places/tests/bookmarks/head_bookmarks.js index 7aa7828290c4..419f21f48ac2 100644 --- a/toolkit/components/places/tests/bookmarks/head_bookmarks.js +++ b/toolkit/components/places/tests/bookmarks/head_bookmarks.js @@ -37,169 +37,17 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -do_get_profile(); - -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - - try { - return dbConn = storageService.openDatabase(file); - } - catch(ex) {} - - return null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_384228.js", - "test_395593.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} +// Put any other stuff relative to this test folder below. diff --git a/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js b/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js index 1872659e34be..46228c8b29fe 100644 --- a/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js +++ b/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js @@ -222,7 +222,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js b/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js index 895074cd285c..b21f27351a04 100644 --- a/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js +++ b/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js @@ -145,7 +145,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js b/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js index b665674e2a7b..ce90f547562e 100644 --- a/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js +++ b/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js @@ -157,7 +157,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js b/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js index 60220d682a69..9526fef29c52 100644 --- a/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js +++ b/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js @@ -91,7 +91,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_448584.js b/toolkit/components/places/tests/bookmarks/test_448584.js index 859d15b03818..ad82bae8ed50 100644 --- a/toolkit/components/places/tests/bookmarks/test_448584.js +++ b/toolkit/components/places/tests/bookmarks/test_448584.js @@ -103,7 +103,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_458683.js b/toolkit/components/places/tests/bookmarks/test_458683.js index a1e42a4767d7..a3415ee9e83f 100644 --- a/toolkit/components/places/tests/bookmarks/test_458683.js +++ b/toolkit/components/places/tests/bookmarks/test_458683.js @@ -134,7 +134,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_restore_guids.js b/toolkit/components/places/tests/bookmarks/test_restore_guids.js index 2f2cb6e05261..5eec3c7d54da 100644 --- a/toolkit/components/places/tests/bookmarks/test_restore_guids.js +++ b/toolkit/components/places/tests/bookmarks/test_restore_guids.js @@ -79,7 +79,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/expiration/head_expiration.js b/toolkit/components/places/tests/expiration/head_expiration.js index 0a7829f94a8b..799f84b1dd47 100644 --- a/toolkit/components/places/tests/expiration/head_expiration.js +++ b/toolkit/components/places/tests/expiration/head_expiration.js @@ -37,245 +37,21 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -// If there's no location registered for the profile direcotry, register one now. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var profileDir = null; -try { - profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile); -} catch (e) {} -if (!profileDir) { - // Register our own provider for the profile directory. - // It will simply return the current directory. - var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_USER_PROFILE_50_DIR) - return dirSvc.get("CurProcD", Ci.nsIFile); - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("CurProcD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); -} +// Put any other stuff relative to this test folder below. -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = DBConn() - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // Print the column names. - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // Print the row. - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); -} - -/** - * Function tests to see if the place associated with the bookmark with id - * aBookmarkId has the uri aExpectedURI. The event will call do_test_finished() - * if aFinish is true. - * - * @param aBookmarkId - * The bookmark to check against. - * @param aExpectedURI - * The URI we expect to be in moz_places. - * @param aExpected - * Indicates if we expect to get a result or not. - * @param [optional] aFinish - * Indicates if the test should be completed or not. - */ -function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFinish) -{ - let db = DBConn(); - let stmt = db.createStatement( - "SELECT moz_places.url " + - "FROM moz_bookmarks INNER JOIN moz_places " + - "ON moz_bookmarks.fk = moz_places.id " + - "WHERE moz_bookmarks.id = ?1" - ); - stmt.bindInt64Parameter(0, aBookmarkId); - - if (aExpected) { - do_check_true(stmt.executeStep()); - do_check_eq(stmt.getUTF8String(0), aExpectedURI); - } - else { - do_check_false(stmt.executeStep()); - } - stmt.reset(); - stmt.finalize(); - - if (aFinish) - do_test_finished(); -} - -/** - * Function tests to see if the place associated with the visit with id aVisitId - * has the uri aExpectedURI. The event will call do_test_finished() if aFinish is - * true. - * - * @param aVisitId - * The visit to check against. - * @param aExpectedURI - * The URI we expect to be in moz_places. - * @param aExpected - * Indicates if we expect to get a result or not. - * @param [optional] aFinish - * Indicates if the test should be completed or not. - */ -function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) -{ - let db = DBConn(); - let stmt = db.createStatement( - "SELECT moz_places.url " + - "FROM moz_historyvisits INNER JOIN moz_places " + - "ON moz_historyvisits.place_id = moz_places.id " + - "WHERE moz_historyvisits.id = ?1" - ); - stmt.bindInt64Parameter(0, aVisitId); - - if (aExpected) { - do_check_true(stmt.executeStep()); - do_check_eq(stmt.getUTF8String(0), aExpectedURI); - } - else { - do_check_false(stmt.executeStep()); - } - stmt.reset(); - stmt.finalize(); - - if (aFinish) - do_test_finished(); -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - - try { - return dbConn = storageService.openDatabase(file); - } - catch(ex) {} - - return null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// Simulates a Places shutdown. -function shutdownPlaces() -{ - const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown"; - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsIObserver); - hs.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let expire = Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsIObserver); - expire.observe(null, TOPIC_XPCOM_SHUTDOWN, null); -} // Simulates an expiration at shutdown. function shutdownExpiration() @@ -285,6 +61,7 @@ function shutdownExpiration() expire.observe(null, TOPIC_XPCOM_SHUTDOWN, null); } + /** * Causes expiration component to start, otherwise it would wait for the first * history notification. @@ -293,6 +70,7 @@ function force_expiration_start() { Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsISupports); } + /** * Forces an expiration run. */ @@ -304,66 +82,48 @@ function force_expiration_step(aLimit) { expire.observe(null, TOPIC_DEBUG_START_EXPIRATION, aLimit); } -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let observer = { - observe: function(aSubject, aTopic, aData) { - os.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } - }; - os.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages(); -} /** * Expiration preferences helpers. */ -let prefs = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); function setInterval(aNewInterval) { - prefs.setIntPref("places.history.expiration.interval_seconds", aNewInterval); + Services.prefs.setIntPref("places.history.expiration.interval_seconds", aNewInterval); } function getInterval() { - return prefs.getIntPref("places.history.expiration.interval_seconds"); + return Services.prefs.getIntPref("places.history.expiration.interval_seconds"); } function clearInterval() { try { - prefs.clearUserPref("places.history.expiration.interval_seconds"); + Services.prefs.clearUserPref("places.history.expiration.interval_seconds"); } catch(ex) {} } + function setMaxPages(aNewMaxPages) { - prefs.setIntPref("places.history.expiration.max_pages", aNewMaxPages); + Services.prefs.setIntPref("places.history.expiration.max_pages", aNewMaxPages); } function getMaxPages() { - return prefs.getIntPref("places.history.expiration.max_pages"); + return Services.prefs.getIntPref("places.history.expiration.max_pages"); } function clearMaxPages() { try { - prefs.clearUserPref("places.history.expiration.max_pages"); + Services.prefs.clearUserPref("places.history.expiration.max_pages"); } catch(ex) {} } + function setHistoryEnabled(aHistoryEnabled) { - prefs.setBoolPref("places.history.enabled", aHistoryEnabled); + Services.prefs.setBoolPref("places.history.enabled", aHistoryEnabled); } function getHistoryEnabled() { - return prefs.getBoolPref("places.history.enabled"); + return Services.prefs.getBoolPref("places.history.enabled"); } function clearHistoryEnabled() { try { - prefs.clearUserPref("places.history.enabled"); + Services.prefs.clearUserPref("places.history.enabled"); } catch(ex) {} } diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_history.js b/toolkit/components/places/tests/expiration/test_annos_expire_history.js index 2c7a8b1ab4a5..981661ad80a3 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_history.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_history.js @@ -45,8 +45,6 @@ * This expiration policy is only valid for page annotations. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_never.js b/toolkit/components/places/tests/expiration/test_annos_expire_never.js index f0fec795abcd..6bc53a0e08c7 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_never.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_never.js @@ -48,8 +48,6 @@ * the item is removed, thus expiration won't handle this case at all. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_policy.js b/toolkit/components/places/tests/expiration/test_annos_expire_policy.js index 4dec324314ef..b96ee9aca1e6 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_policy.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_policy.js @@ -47,8 +47,6 @@ * - EXPIRE_MONTHS: annotation would be expired after 180 days */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. @@ -76,7 +74,6 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, if (aLastModifiedAgeInDays) lastModifiedDate = (now - (aLastModifiedAgeInDays * 86400 * 1000)) * 1000; - let dbConn = DBConn(); let sql; if (typeof(aIdentifier) == "number") { // Item annotation. @@ -100,7 +97,7 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, else do_throw("Wrong identifier type"); - let stmt = dbConn.createStatement(sql); + let stmt = DBConn().createStatement(sql); stmt.params.id = (typeof(aIdentifier) == "number") ? aIdentifier : aIdentifier.spec; stmt.params.expire_date = expireDate; diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_session.js b/toolkit/components/places/tests/expiration/test_annos_expire_session.js index 31ae86fa1f0b..0529149d9e63 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_session.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_session.js @@ -43,8 +43,6 @@ * Session annotations should be expired when browsing session ends. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_notifications.js b/toolkit/components/places/tests/expiration/test_notifications.js index 6040bbf4aa57..8b9e704d2515 100644 --- a/toolkit/components/places/tests/expiration/test_notifications.js +++ b/toolkit/components/places/tests/expiration/test_notifications.js @@ -43,8 +43,6 @@ * Ensure that History (through category cache) notifies us just once. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js b/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js index b4dffe9981ed..04c07dc1d2db 100644 --- a/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js +++ b/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js @@ -43,8 +43,6 @@ * Expiring a full page should fire an onDeleteURI notification. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js b/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js index c71747d352c8..13c9ab64e6e6 100644 --- a/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js +++ b/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js @@ -44,8 +44,6 @@ * onDeleteVisits notification. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_pref_interval.js b/toolkit/components/places/tests/expiration/test_pref_interval.js index ba7774baf269..e88e4eef8032 100644 --- a/toolkit/components/places/tests/expiration/test_pref_interval.js +++ b/toolkit/components/places/tests/expiration/test_pref_interval.js @@ -47,7 +47,6 @@ * If the pref is set to a number <= 0 we will use the default value. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; const MAX_WAIT_SECONDS = 4; const INTERVAL_CUSHION = 2; diff --git a/toolkit/components/places/tests/expiration/test_pref_maxpages.js b/toolkit/components/places/tests/expiration/test_pref_maxpages.js index 6c7f194f1ecb..54fbf712f60b 100644 --- a/toolkit/components/places/tests/expiration/test_pref_maxpages.js +++ b/toolkit/components/places/tests/expiration/test_pref_maxpages.js @@ -47,8 +47,6 @@ * If the pref is set to a number < 0 we will use the default value. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_removeAllPages.js b/toolkit/components/places/tests/expiration/test_removeAllPages.js index d7914996f82d..cdf6302b0b1d 100644 --- a/toolkit/components/places/tests/expiration/test_removeAllPages.js +++ b/toolkit/components/places/tests/expiration/test_removeAllPages.js @@ -44,8 +44,6 @@ * annos. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. @@ -73,7 +71,6 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, if (aLastModifiedAgeInDays) lastModifiedDate = (now - (aLastModifiedAgeInDays * 86400 * 1000)) * 1000; - let dbConn = DBConn(); let sql; if (typeof(aIdentifier) == "number") { // Item annotation. @@ -97,7 +94,7 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, else do_throw("Wrong identifier type"); - let stmt = dbConn.createStatement(sql); + let stmt = DBConn().createStatement(sql); stmt.params.id = (typeof(aIdentifier) == "number") ? aIdentifier : aIdentifier.spec; stmt.params.expire_date = expireDate; diff --git a/toolkit/components/places/tests/head_common.js b/toolkit/components/places/tests/head_common.js new file mode 100644 index 000000000000..51cd5c0a1ad3 --- /dev/null +++ b/toolkit/components/places/tests/head_common.js @@ -0,0 +1,504 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** 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 Places Unit Tests Code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +const NS_APP_USER_PROFILE_50_DIR = "ProfD"; +const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; +const NS_APP_HISTORY_50_FILE = "UHist"; +const NS_APP_BOOKMARKS_50_FILE = "BMarks"; + +const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; +const TOPIC_SHUTDOWN = "xpcom-shutdown"; +const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete"; +const TOPIC_PLACES_DATABASE_LOCKED = "places-database-locked"; + +// Shortcuts to transactions type. +const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK; +const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED; +const TRANSITION_BOOKMARK = Ci.nsINavHistoryService.TRANSITION_BOOKMARK; +const TRANSITION_EMBED = Ci.nsINavHistoryService.TRANSITION_EMBED; +const TRANSITION_FRAMED_LINK = Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK; +const TRANSITION_REDIRECT_PERMANENT = Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT; +const TRANSITION_REDIRECT_TEMPORARY = Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY; +const TRANSITION_DOWNLOAD = Ci.nsINavHistoryService.TRANSITION_DOWNLOAD; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyGetter(this, "Services", function() { + Cu.import("resource://gre/modules/Services.jsm"); + return Services; +}); + +XPCOMUtils.defineLazyGetter(this, "NetUtil", function() { + Cu.import("resource://gre/modules/NetUtil.jsm"); + return NetUtil; +}); + +XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() { + Cu.import("resource://gre/modules/utils.js"); + return PlacesUtils; +}); + + +function LOG(aMsg) { + aMsg = ("*** PLACES TESTS: " + aMsg); + Services.console.logStringMessage(aMsg); + print(aMsg); +} + + +let gTestDir = do_get_cwd(); + + +// Initialize profile. +let gProfD = do_get_profile(); + +// Add our own dirprovider for old history.dat. +let (provider = { + getFile: function(prop, persistent) { + persistent.value = true; + if (prop == NS_APP_HISTORY_50_FILE) { + let histFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + histFile.append("history.dat"); + return histFile; + } + throw Cr.NS_ERROR_FAILURE; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]) + }) +{ + Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIDirectoryService). + QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); +} + + +// Remove any old database. +clearDB(); + + +/** + * Shortcut to create a nsIURI. + * + * @param aSpec + * URLString of the uri. + */ +function uri(aSpec) NetUtil.newURI(aSpec); + + +/** + * Gets the database connection. If the Places connection is invalid it will + * try to create a new connection. + * + * @return The database connection or null if unable to get one. + */ +function DBConn() { + let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) + .DBConnection; + if (db.connectionReady) + return db; + + // If the database has been closed, then we need to open a new connection. + let file = Services.dirsvc.get('ProfD', Ci.nsIFile); + file.append("places.sqlite"); + return Services.storage.openDatabase(file); +}; + + +/** + * Reads the data from the specified nsIFile, and returns an array of bytes. + * + * @param aFile + * The nsIFile to read from. + */ +function readFileData(aFile) { + let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + // init the stream as RD_ONLY, -1 == default permissions. + inputStream.init(aFile, 0x01, -1, null); + let size = inputStream.available(); + + // use a binary input stream to grab the bytes. + let bis = Cc["@mozilla.org/binaryinputstream;1"]. + createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(inputStream); + + let bytes = bis.readByteArray(size); + + if (size != bytes.length) + throw "Didn't read expected number of bytes"; + + return bytes; +} + + +/** + * Compares two arrays, and returns true if they are equal. + * + * @param aArray1 + * First array to compare. + * @param aArray2 + * Second array to compare. + */ +function compareArrays(aArray1, aArray2) { + if (aArray1.length != aArray2.length) { + print("compareArrays: array lengths differ\n"); + return false; + } + + for (let i = 0; i < aArray1.length; i++) { + if (aArray1[i] != aArray2[i]) { + print("compareArrays: arrays differ at index " + i + ": " + + "(" + aArray1[i] + ") != (" + aArray2[i] +")\n"); + return false; + } + } + + return true; +} + + +/** + * Deletes a previously created sqlite file from the profile folder. + */ +function clearDB() { + try { + let file = Services.dirsvc.get('ProfD', Ci.nsIFile); + file.append("places.sqlite"); + if (file.exists()) + file.remove(false); + } catch(ex) { dump("Exception: " + ex); } +} + + +/** + * Dumps the rows of a table out to the console. + * + * @param aName + * The name of the table or view to output. + */ +function dump_table(aName) +{ + let stmt = DBConn().createStatement("SELECT * FROM " + aName); + + print("\n*** Printing data from " + aName); + let count = 0; + while (stmt.executeStep()) { + let columns = stmt.numEntries; + + if (count == 0) { + // Print the column names. + for (let i = 0; i < columns; i++) + dump(stmt.getColumnName(i) + "\t"); + dump("\n"); + } + + // Print the rows. + for (let i = 0; i < columns; i++) { + switch (stmt.getTypeOfIndex(i)) { + case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: + dump("NULL\t"); + break; + case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: + dump(stmt.getInt64(i) + "\t"); + break; + case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: + dump(stmt.getDouble(i) + "\t"); + break; + case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: + dump(stmt.getString(i) + "\t"); + break; + } + } + dump("\n"); + + count++; + } + print("*** There were a total of " + count + " rows of data.\n"); + + stmt.finalize(); +} + + +/** + * Removes all bookmarks and checks for correct cleanup + */ +function remove_all_bookmarks() { + let PU = PlacesUtils; + // Clear all bookmarks + PU.bookmarks.removeFolderChildren(PU.bookmarks.bookmarksMenuFolder); + PU.bookmarks.removeFolderChildren(PU.bookmarks.toolbarFolder); + PU.bookmarks.removeFolderChildren(PU.bookmarks.unfiledBookmarksFolder); + // Check for correct cleanup + check_no_bookmarks(); +} + + +/** + * Checks that we don't have any bookmark + */ +function check_no_bookmarks() { + let query = PlacesUtils.history.getNewQuery(); + let folders = [ + PlacesUtils.bookmarks.toolbarFolder, + PlacesUtils.bookmarks.bookmarksMenuFolder, + PlacesUtils.bookmarks.unfiledBookmarksFolder, + ]; + query.setFolders(folders, 3); + let options = PlacesUtils.history.getNewQueryOptions(); + options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; + let root = PlacesUtils.history.executeQuery(query, options).root; + root.containerOpen = true; + do_check_eq(root.childCount, 0); + root.containerOpen = false; +} + + + +/** + * Sets title synchronously for a page in moz_places synchronously. + * History.SetPageTitle uses LAZY_ADD so we can't rely on it. + * + * @param aURI + * An nsIURI to set the title for. + * @param aTitle + * The title to set the page to. + * @throws if the page is not found in the database. + * + * @note this function only exists because we have no API to do this. It should + * be added in bug 421897. + */ +function setPageTitle(aURI, aTitle) { + // Check that the page exists. + let stmt = DBConn().createStatement( + "SELECT id FROM moz_places_view WHERE url = :url" + ); + stmt.params.url = aURI.spec; + try { + if (!stmt.executeStep()) { + do_throw("Unable to find page " + aURI.spec); + return; + } + } + finally { + stmt.finalize(); + } + + // Update the title + stmt = DBConn().createStatement( + "UPDATE moz_places_view SET title = :title WHERE url = :url" + ); + stmt.params.title = aTitle; + stmt.params.url = aURI.spec; + try { + stmt.execute(); + } + finally { + stmt.finalize(); + } +} + + +/** + * Clears history invoking callback when done. + * + * @param aCallback + * Callback function to be called once clear history has finished. + */ +function waitForClearHistory(aCallback) { + let observer = { + observe: function(aSubject, aTopic, aData) { + Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED); + aCallback(); + } + }; + Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); + + PlacesUtils.bhistory.removeAllPages(); +} + + +/** + * Simulates a Places shutdown. + */ +function shutdownPlaces() +{ + let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsIObserver); + hs.observe(null, TOPIC_SHUTDOWN, null); + + let sync = Cc["@mozilla.org/places/sync;1"]. + getService(Ci.nsIObserver); + sync.observe(null, TOPIC_SHUTDOWN, null); + + let expire = Cc["@mozilla.org/places/expiration;1"]. + getService(Ci.nsIObserver); + expire.observe(null, TOPIC_SHUTDOWN, null); +} + + +/** + * Creates a bookmarks.html file in the profile folder from a given source file. + * + * @param aFilename + * Name of the file to copy to the profile folder. This file must + * exist in the directory that contains the test files. + * + * @return nsIFile object for the file. + */ +function create_bookmarks_html(aFilename) { + if (!aFilename) + do_throw("you must pass a filename to create_bookmarks_html function"); + remove_bookmarks_html(); + let bookmarksHTMLFile = gTestDir.clone(); + bookmarksHTMLFile.append(aFilename); + do_check_true(bookmarksHTMLFile.exists()); + bookmarksHTMLFile.copyTo(gProfD, FILENAME_BOOKMARKS_HTML); + let profileBookmarksHTMLFile = gProfD.clone(); + profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); + do_check_true(profileBookmarksHTMLFile.exists()); + return profileBookmarksHTMLFile; +} + + +/** + * Remove bookmarks.html file from the profile folder. + */ +function remove_bookmarks_html() { + let profileBookmarksHTMLFile = gProfD.clone(); + profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); + if (profileBookmarksHTMLFile.exists()) { + profileBookmarksHTMLFile.remove(false); + do_check_false(profileBookmarksHTMLFile.exists()); + } +} + + +/** + * Check bookmarks.html file exists in the profile folder. + * + * @return nsIFile object for the file. + */ +function check_bookmarks_html() { + let profileBookmarksHTMLFile = gProfD.clone(); + profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); + do_check_true(profileBookmarksHTMLFile.exists()); + return profileBookmarksHTMLFile; +} + + +/** + * Creates a JSON backup in the profile folder folder from a given source file. + * + * @param aFilename + * Name of the file to copy to the profile folder. This file must + * exist in the directory that contains the test files. + * + * @return nsIFile object for the file. + */ +function create_JSON_backup(aFilename) { + if (!aFilename) + do_throw("you must pass a filename to create_JSON_backup function"); + remove_all_JSON_backups(); + let bookmarksBackupDir = gProfD.clone(); + bookmarksBackupDir.append("bookmarkbackups"); + if (!bookmarksBackupDir.exists()) { + bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); + do_check_true(bookmarksBackupDir.exists()); + } + let bookmarksJSONFile = gTestDir.clone(); + bookmarksJSONFile.append(aFilename); + do_check_true(bookmarksJSONFile.exists()); + bookmarksJSONFile.copyTo(bookmarksBackupDir, FILENAME_BOOKMARKS_JSON); + let profileBookmarksJSONFile = bookmarksBackupDir.clone(); + profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); + do_check_true(profileBookmarksJSONFile.exists()); + return profileBookmarksJSONFile; +} + + +/** + * Remove bookmarksbackup dir and all backups from the profile folder. + */ +function remove_all_JSON_backups() { + let bookmarksBackupDir = gProfD.clone(); + bookmarksBackupDir.append("bookmarkbackups"); + if (bookmarksBackupDir.exists()) { + bookmarksBackupDir.remove(true); + do_check_false(bookmarksBackupDir.exists()); + } +} + + +/** + * Check a JSON backup file for today exists in the profile folder. + * + * @return nsIFile object for the file. + */ +function check_JSON_backup() { + let profileBookmarksJSONFile = gProfD.clone(); + profileBookmarksJSONFile.append("bookmarkbackups"); + profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); + do_check_true(profileBookmarksJSONFile.exists()); + return profileBookmarksJSONFile; +} + + +// These tests are known to randomly fail due to bug 507790 when database +// flushes are active, so we turn off syncing for them. +let (randomFailingSyncTests = [ + "test_multi_word_tags.js", + "test_removeVisitsByTimeframe.js", + "test_utils_getURLsForContainerNode.js", + "test_exclude_livemarks.js", + "test_402799.js", + "test_results-as-visit.js", + "test_sorting.js", + "test_redirectsMode.js", + "test_384228.js", + "test_395593.js", + "test_containersQueries_sorting.js", + "test_browserGlue_smartBookmarks.js", + "test_browserGlue_distribution.js", +]) { + let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; + if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { + print("Test " + currentTestFilename + + " is known random due to bug 507790, disabling PlacesDBFlush."); + let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); + sync.observe(null, "places-debug-stop-sync", null); + } +} diff --git a/toolkit/components/places/tests/network/head_network.js b/toolkit/components/places/tests/network/head_network.js index f6bda7eb5fd2..8832f3f521a7 100644 --- a/toolkit/components/places/tests/network/head_network.js +++ b/toolkit/components/places/tests/network/head_network.js @@ -37,292 +37,16 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - -// This will also define Cc, Ci. +// This will also define Cc, Ci, Cr, Cu. do_load_httpd_js(); -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -do_get_profile(); +// Put any other stuff relative to this test folder below. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("ProfD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -/* - * Reads the data from the specified nsIFile, and returns an array of bytes. - */ -function readFileData(aFile) { - var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - // init the stream as RD_ONLY, -1 == default permissions. - inputStream.init(aFile, 0x01, -1, null); - var size = inputStream.available(); - - // use a binary input stream to grab the bytes. - var bis = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(inputStream); - - var bytes = bis.readByteArray(size); - - if (size != bytes.length) - throw "Didn't read expected number of bytes"; - - return bytes; -} - -/* - * Compares two arrays, and returns true if they are equal. - */ -function compareArrays(aArray1, aArray2) { - if (aArray1.length != aArray2.length) { - print("compareArrays: array lengths differ\n"); - return false; - } - - for (var i = 0; i < aArray1.length; i++) { - if (aArray1[i] != aArray2[i]) { - print("compareArrays: arrays differ at index " + i + ": " + - "(" + aArray1[i] + ") != (" + aArray2[i] +")\n"); - return false; - } - } - - return true; -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Sets title synchronously for a page in moz_places synchronously. - * History.SetPageTitle uses LAZY_ADD so we can't rely on it. - * - * @param aURI - * An nsIURI to set the title for. - * @param aTitle - * The title to set the page to. - * @throws if the page is not found in the database. - * - * @note this function only exists because we have no API to do this. It should - * be added in bug 421897. - */ -function setPageTitle(aURI, aTitle) { - let dbConn = DBConn(); - // Check that the page exists. - let stmt = dbConn.createStatement( - "SELECT id FROM moz_places_view WHERE url = :url"); - stmt.params.url = aURI.spec; - try { - if (!stmt.executeStep()) { - do_throw("Unable to find page " + aURIString); - return; - } - } - finally { - stmt.finalize(); - } - - // Update the title - stmt = dbConn.createStatement( - "UPDATE moz_places_view SET title = :title WHERE url = :url"); - stmt.params.title = aTitle; - stmt.params.url = aURI.spec; - try { - stmt.execute(); - } - finally { - stmt.finalize(); - } -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let observer = { - observe: function(aSubject, aTopic, aData) { - os.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } - }; - os.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages(); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} diff --git a/toolkit/components/places/tests/network/test_history_redirects.js b/toolkit/components/places/tests/network/test_history_redirects.js index 2bead1dd08b1..224d5aa356aa 100644 --- a/toolkit/components/places/tests/network/test_history_redirects.js +++ b/toolkit/components/places/tests/network/test_history_redirects.js @@ -44,9 +44,6 @@ let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. let bh = hs.QueryInterface(Ci.nsIBrowserHistory); let ghist3 = hs.QueryInterface(Ci.nsIGlobalHistory3); -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/NetUtil.jsm"); - const PERMA_REDIR_PATH = "/permaredir"; const TEMP_REDIR_PATH = "/tempredir"; const FOUND_PATH = "/found"; @@ -110,8 +107,7 @@ function run_test() { } function continue_test() { - let dbConn = DBConn(); - let stmt = dbConn.createStatement( + let stmt = DBConn().createStatement( "SELECT v.id, h.url, v.from_visit, v.visit_date, v.visit_type, v.session " + "FROM moz_historyvisits_view v " + "JOIN moz_places_view h on h.id = v.place_id " + diff --git a/toolkit/components/places/tests/queries/head_queries.js b/toolkit/components/places/tests/queries/head_queries.js index e6f42974df38..35754e733ac9 100644 --- a/toolkit/components/places/tests/queries/head_queries.js +++ b/toolkit/components/places/tests/queries/head_queries.js @@ -35,12 +35,22 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + // Some Useful Date constants - PRTime uses microseconds, so convert const DAY_MICROSEC = 86400000000; @@ -52,100 +62,6 @@ const tomorrow = today + DAY_MICROSEC; const old = today - (DAY_MICROSEC * 3); const futureday = today + (DAY_MICROSEC * 3); -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - print(aMsg); -} - -// If there's no location registered for the profile directory, register one now. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var profileDir = do_get_profile(); - -var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = profileDir.clone(); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -// Get our interfaces -try { - var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); -} catch(ex) { - do_throw("Could not get history service\n"); -} - -try { - var bhistsvc = histsvc.QueryInterface(Ci.nsIBrowserHistory); -} catch(ex) { - do_throw("Could not get browser history service\n"); -} - -try { - var annosvc = Cc["@mozilla.org/browser/annotation-service;1"]. - getService(Ci.nsIAnnotationService); -} catch(ex) { - do_throw("Could not get annotation service\n"); -} - -try { - var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); -} catch (ex) { - do_throw("Could not get bookmark service\n"); -} - -try { - var tagssvc = Cc["@mozilla.org/browser/tagging-service;1"]. - getService(Ci.nsITaggingService); -} catch(ex) { - do_throw("Could not get tagging service\n"); -} - -try { - var faviconsvc = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); -} catch(ex) { - do_throw("Could not get favicon service\n"); -} - -try { - var lmsvc = Cc["@mozilla.org/browser/livemark-service;2"]. - getService(Ci.nsILivemarkService); -} catch(ex) { - do_throw("Could not get livemark service\n"); -} /** * Generalized function to pull in an array of objects of data and push it into @@ -154,6 +70,7 @@ try { */ function populateDB(aArray) { aArray.forEach(function(data) { + dump_table("moz_bookmarks"); try { // make the data object into a query data object in order to create proper // default values for anything left unspecified @@ -161,23 +78,21 @@ function populateDB(aArray) { if (qdata.isVisit) { // Then we should add a visit for this node var referrer = qdata.referrer ? uri(qdata.referrer) : null; - var visitId = histsvc.addVisit(uri(qdata.uri), qdata.lastVisit, - referrer, qdata.transType, - qdata.isRedirect, qdata.sessionID); + var visitId = PlacesUtils.history.addVisit(uri(qdata.uri), qdata.lastVisit, + referrer, qdata.transType, + qdata.isRedirect, qdata.sessionID); do_check_true(visitId > 0); if (qdata.title && !qdata.isDetails) { // Set the page title synchronously, otherwise setPageTitle is LAZY. - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("UPDATE moz_places_view " + - "SET title = :title WHERE url = :url"); + let stmt = DBConn().createStatement( + "UPDATE moz_places_view SET title = :title WHERE url = :url" + ); stmt.params.title = qdata.title; stmt.params.url = qdata.uri; try { stmt.execute(); // Force a notification so results are updated. - histsvc.runInBatchMode({runBatched: function(){}}, null); + PlacesUtils.history.runInBatchMode({runBatched: function(){}}, null); } finally { stmt.finalize(); @@ -186,17 +101,14 @@ function populateDB(aArray) { if (qdata.visitCount && !qdata.isDetails) { // Set a fake visit_count, this is not a real count but can be used // to test sorting by visit_count. - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("UPDATE moz_places_view " + - "SET visit_count = :vc WHERE url = :url"); + let stmt = DBConn().createStatement( + "UPDATE moz_places_view SET visit_count = :vc WHERE url = :url"); stmt.params.vc = qdata.visitCount; stmt.params.url = qdata.uri; try { stmt.execute(); // Force a notification so results are updated. - histsvc.runInBatchMode({runBatched: function(){}}, null); + PlacesUtils.history.runInBatchMode({runBatched: function(){}}, null); } finally { stmt.finalize(); @@ -206,57 +118,71 @@ function populateDB(aArray) { if (qdata.isDetails) { // Then we add extraneous page details for testing - bhistsvc.addPageWithDetails(uri(qdata.uri), qdata.title, qdata.lastVisit); + PlacesUtils.history.addPageWithDetails(uri(qdata.uri), + qdata.title, qdata.lastVisit); } if (qdata.markPageAsTyped){ - bhistsvc.markPageAsTyped(uri(qdata.uri)); + PlacesUtils.bhistory.markPageAsTyped(uri(qdata.uri)); } if (qdata.hidePage){ - bhistsvc.hidePage(uri(qdata.uri)); + PlacesUtils.bhistory.hidePage(uri(qdata.uri)); } if (qdata.isPageAnnotation) { if (qdata.removeAnnotation) - annosvc.removePageAnnotation(uri(qdata.uri), qdata.annoName); + PlacesUtils.annotations.removePageAnnotation(uri(qdata.uri), + qdata.annoName); else { - annosvc.setPageAnnotation(uri(qdata.uri), - qdata.annoName, qdata.annoVal, - qdata.annoFlags, qdata.annoExpiration); + PlacesUtils.annotations.setPageAnnotation(uri(qdata.uri), + qdata.annoName, + qdata.annoVal, + qdata.annoFlags, + qdata.annoExpiration); } } if (qdata.isItemAnnotation) { if (qdata.removeAnnotation) - annosvc.removeItemAnnotation(qdata.itemId, qdata.annoName); + PlacesUtils.annotations.removeItemAnnotation(qdata.itemId, + qdata.annoName); else { - annosvc.setItemAnnotation(qdata.itemId, qdata.annoName, qdata.annoVal, - qdata.annoFlags, qdata.annoExpiration); + PlacesUtils.annotations.setItemAnnotation(qdata.itemId, + qdata.annoName, + qdata.annoVal, + qdata.annoFlags, + qdata.annoExpiration); } } if (qdata.isPageBinaryAnnotation) { if (qdata.removeAnnotation) - annosvc.removePageAnnotation(uri(qdata.uri), qdata.annoName); + PlacesUtils.annotations.removePageAnnotation(uri(qdata.uri), + qdata.annoName); else { - annosvc.setPageAnnotationBinary(uri(qdata.uri), qdata.annoName, - qdata.binarydata, - qdata.binaryDataLength, - qdata.annoMimeType, qdata.annoFlags, - qdata.annoExpiration); + PlacesUtils.annotations.setPageAnnotationBinary(uri(qdata.uri), + qdata.annoName, + qdata.binarydata, + qdata.binaryDataLength, + qdata.annoMimeType, + qdata.annoFlags, + qdata.annoExpiration); } } if (qdata.isItemBinaryAnnotation) { if (qdata.removeAnnotation) - annosvc.removeItemAnnotation(qdata.itemId, qdata.annoName); + PlacesUtils.annotations.removeItemAnnotation(qdata.itemId, + qdata.annoName); else { - annosvc.setItemAnnotationBinary(qdata.itemId, qdata.annoName, - qdata.binaryData, - qdata.binaryDataLength, - qdata.annoMimeType, qdata.annoFlags, - qdata.annoExpiration); + PlacesUtils.annotations.setItemAnnotationBinary(qdata.itemId, + qdata.annoName, + qdata.binaryData, + qdata.binaryDataLength, + qdata.annoMimeType, + qdata.annoFlags, + qdata.annoExpiration); } } @@ -264,42 +190,54 @@ function populateDB(aArray) { // Not planning on doing deep testing of favIcon service so these two // calls should be sufficient to get favicons into the database try { - faviconsvc.setFaviconData(uri(qdata.faviconURI), qdata.favicon, - qdata.faviconLen, qdata.faviconMimeType, - qdata.faviconExpiration); + PlacesUtils.favicons.setFaviconData(uri(qdata.faviconURI), + qdata.favicon, + qdata.faviconLen, + qdata.faviconMimeType, + qdata.faviconExpiration); } catch (ex) {} - faviconsvc.setFaviconUrlForPage(uri(qdata.uri), uri(qdata.faviconURI)); + PlacesUtils.favicons.setFaviconUrlForPage(uri(qdata.uri), + uri(qdata.faviconURI)); } if (qdata.isFolder) { - let folderId = bmsvc.createFolder(qdata.parentFolder, qdata.title, qdata.index); + let folderId = PlacesUtils.bookmarks.createFolder(qdata.parentFolder, + qdata.title, + qdata.index); if (qdata.readOnly) - bmsvc.setFolderReadonly(folderId, true); + PlacesUtils.bookmarks.setFolderReadonly(folderId, true); } if (qdata.isLivemark) { - lmsvc.createLivemark(qdata.parentFolder, qdata.title, uri(qdata.uri), - uri(qdata.feedURI), qdata.index); + PlacesUtils.livemarks.createLivemark(qdata.parentFolder, + qdata.title, + uri(qdata.uri), + uri(qdata.feedURI), + qdata.index); } if (qdata.isBookmark) { - let itemId = bmsvc.insertBookmark(qdata.parentFolder, uri(qdata.uri), - qdata.index, qdata.title); + let itemId = PlacesUtils.bookmarks.insertBookmark(qdata.parentFolder, + uri(qdata.uri), + qdata.index, + qdata.title); if (qdata.keyword) - bmsvc.setKeywordForBookmark(itemId, qdata.keyword); + PlacesUtils.bookmarks.setKeywordForBookmark(itemId, qdata.keyword); if (qdata.dateAdded) - bmsvc.setItemDateAdded(itemId, qdata.dateAdded); + PlacesUtils.bookmarks.setItemDateAdded(itemId, qdata.dateAdded); if (qdata.lastModified) - bmsvc.setItemLastModified(itemId, qdata.lastModified); + PlacesUtils.bookmarks.setItemLastModified(itemId, qdata.lastModified); } if (qdata.isTag) { - tagssvc.tagURI(uri(qdata.uri), qdata.tagArray); + PlacesUtils.tagging.tagURI(uri(qdata.uri), qdata.tagArray); } if (qdata.isDynContainer) { - bmsvc.createDynamicContainer(qdata.parentFolder, qdata.title, - qdata.contractId, qdata.index); + PlacesUtils.bookmarks.createDynamicContainer(qdata.parentFolder, + qdata.title, + qdata.contractId, + qdata.index); } } catch (ex) { // use the data object here in case instantiation of qdata failed @@ -309,6 +247,7 @@ function populateDB(aArray) { }); // End of function and array } + /** * The Query Data Object - this object encapsulates data for our queries and is * used to parameterize our calls to the Places APIs to put data into the @@ -326,7 +265,7 @@ function queryData(obj) { this.uri = obj.uri ? obj.uri : ""; this.lastVisit = obj.lastVisit ? obj.lastVisit : today; this.referrer = obj.referrer ? obj.referrer : null; - this.transType = obj.transType ? obj.transType : histsvc.TRANSITION_TYPED; + this.transType = obj.transType ? obj.transType : Ci.nsINavHistoryService.TRANSITION_TYPED; this.isRedirect = obj.isRedirect ? obj.isRedirect : false; this.sessionID = obj.sessionID ? obj.sessionID : 0; this.isDetails = obj.isDetails ? obj.isDetails : false; @@ -357,9 +296,10 @@ function queryData(obj) { this.faviconExpiration = obj.faviconExpiration ? obj.faviconExpiration : futureday; this.isLivemark = obj.isLivemark ? obj.isLivemark : false; - this.parentFolder = obj.parentFolder ? obj.parentFolder : bmsvc.placesRoot; + this.parentFolder = obj.parentFolder ? obj.parentFolder + : PlacesUtils.placesRootId; this.feedURI = obj.feedURI ? obj.feedURI : ""; - this.index = obj.index ? obj.index : bmsvc.DEFAULT_INDEX; + this.index = obj.index ? obj.index : PlacesUtils.bookmarks.DEFAULT_INDEX; this.isFolder = obj.isFolder ? obj.isFolder : false; this.contractId = obj.contractId ? obj.contractId : ""; this.lastModified = obj.lastModified ? obj.lastModified : today; @@ -376,6 +316,7 @@ function queryData(obj) { // All attributes are set in the constructor above queryData.prototype = { } + /** * Helper function to compare an array of query objects with a result set. * It assumes the array of query objects contains the SAME SORT as the result @@ -409,7 +350,7 @@ function compareArrayToResult(aArray, aRoot) { aArray[i].lastVisit != child.time) do_throw("Expected " + aArray[i].lastVisit + " found " + child.time); if (aArray[i].hasOwnProperty("index") && - aArray[i].index != bmsvc.DEFAULT_INDEX && + aArray[i].index != PlacesUtils.bookmarks.DEFAULT_INDEX && aArray[i].index != child.bookmarkIndex) do_throw("Expected " + aArray[i].index + " found " + child.bookmarkIndex); @@ -422,6 +363,7 @@ function compareArrayToResult(aArray, aRoot) { LOG("Comparing Array to Results passes"); } + /** * Helper function to check to see if one object either is or is not in the * result set. It can accept either a queryData object or an array of queryData @@ -454,6 +396,7 @@ function isInResult(aQueryData, aRoot) { return rv; } + /** * A nice helper function for debugging things. It LOGs the contents of a * result set. @@ -474,107 +417,3 @@ function displayResultSet(aRoot) { aRoot.getChild(i).title + " Visit Time: " + aRoot.getChild(i).time); } } - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - // Clear all bookmarks - bmsvc.removeFolderChildren(bmsvc.bookmarksMenuFolder); - bmsvc.removeFolderChildren(bmsvc.toolbarFolder); - bmsvc.removeFolderChildren(bmsvc.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder, bmsvc.bookmarksMenuFolder, bmsvc.unfiledBookmarksFolder], 3); - var options = histsvc.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = histsvc.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_results-as-visit.js", - "test_sorting.js", - "test_redirectsMode.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} diff --git a/toolkit/components/places/tests/queries/stub-test.js b/toolkit/components/places/tests/queries/stub-test.js index 0132006a8781..367c81426ffd 100644 --- a/toolkit/components/places/tests/queries/stub-test.js +++ b/toolkit/components/places/tests/queries/stub-test.js @@ -43,12 +43,15 @@ * Here is an example of using these to create some bookmark folders: */ // Create Folder1 from root - bmsvc.createFolder(bmsvc.placesRoot, "Folder 1", bmsvc.DEFAULT_INDEX); - var folder1Id = bmsvc.getChildFolder(bmsvc.placesRoot, "Folder 1"); + PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId, "Folder 1", + PlacesUtils.bookmarks.DEFAULT_INDEX); + var folder1Id = PlacesUtils.bookmarks.getChildFolder(PlacesUtils.placesRootId, + "Folder 1"); // Make Folder 1a a child of Folder 1 - bmsvc.createFolder(folder1Id, "Folder 1a", bmsvc.DEFAULT_INDEX); - var folder1aId = bmsvc.getChildFolder(folder1Id, "Folder 1a"); + PlacesUtils.bookmarks.createFolder(folder1Id, "Folder 1a", + PlacesUtils.bookmarks.DEFAULT_INDEX); + var folder1aId = PlacesUtils.bookmarks.getChildFolder(folder1Id, "Folder 1a"); /** * The next thing we do is create a test database for us. Each test runs with @@ -90,15 +93,15 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // Set query attributes here... // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); // Set queryOptions attributes here // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -130,7 +133,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); // Close the container when finished root.containerOpen = false; diff --git a/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js b/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js index f926cdef9334..3ea3dc14d531 100644 --- a/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js +++ b/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js @@ -92,7 +92,7 @@ var testData = [ // Test subdomain included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "moz", isRedirect: true, uri: "http://mail.foo.com/redirect", lastVisit: jan11_800, - transType: histsvc.TRANSITION_LINK}, + transType: PlacesUtils.history.TRANSITION_LINK}, // Test subdomain inclued at the leading time edge {isInQuery: true, isVisit: true, isDetails: true, @@ -158,11 +158,11 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.beginTime = beginTime; query.endTime = endTime; - query.beginTimeReference = histsvc.TIME_RELATIVE_EPOCH; - query.endTimeReference = histsvc.TIME_RELATIVE_EPOCH; + query.beginTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; + query.endTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; query.searchTerms = "moz"; query.domain = "foo.com"; query.domainIsHost = false; @@ -170,7 +170,7 @@ function run_test() { query.annotationIsNot = true; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_URI_ASCENDING; options.resultType = options.RESULTS_AS_URI; // The next two options should be ignored @@ -178,7 +178,7 @@ function run_test() { // options.excludeItems = true; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -246,7 +246,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); LOG("LiveUpdate by updating title in batch mode"); do_check_eq(isInResult({uri: "http://foo.com/changeme2"}, root), true); diff --git a/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js b/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js index abe066152aa5..afe0b382986e 100644 --- a/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js +++ b/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js @@ -96,7 +96,7 @@ var testData = [ // Test uri included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "moz", isRedirect: true, uri: "http://foo.com/redirect", lastVisit: jan11_800, - transType: histsvc.TRANSITION_LINK}, + transType: PlacesUtils.history.TRANSITION_LINK}, // Test leading time edge with tag string is included {isInQuery: true, isVisit: true, isDetails: true, title: "taggariffic", @@ -156,11 +156,11 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.beginTime = beginTime; query.endTime = endTime; - query.beginTimeReference = histsvc.TIME_RELATIVE_EPOCH; - query.endTimeReference = histsvc.TIME_RELATIVE_EPOCH; + query.beginTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; + query.endTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; query.searchTerms = "moz"; query.uri = uri("http://foo.com"); query.uriIsPrefix = true; @@ -168,7 +168,7 @@ function run_test() { query.annotationIsNot = true; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_URI_ASCENDING; options.resultType = options.RESULTS_AS_URI; // The next two options should be ignored @@ -176,7 +176,7 @@ function run_test() { // options.excludeItems = true; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -243,7 +243,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); LOG("LiveUpdate by updating title in batch mode"); do_check_eq(isInResult({uri: "http://foo.com/changeme2"}, root), true); diff --git a/toolkit/components/places/tests/queries/test_containersQueries_sorting.js b/toolkit/components/places/tests/queries/test_containersQueries_sorting.js index 3f4c6897ccb0..61da4f446ee3 100644 --- a/toolkit/components/places/tests/queries/test_containersQueries_sorting.js +++ b/toolkit/components/places/tests/queries/test_containersQueries_sorting.js @@ -199,13 +199,13 @@ function test_query_callback(aSequence) { } // Create a new query with required options. - var query = histsvc.getNewQuery(); - var options = histsvc.getNewQueryOptions(); + var query = PlacesUtils.history.getNewQuery(); + var options = PlacesUtils.history.getNewQueryOptions(); options.resultType = resultType.value; options.sortingMode = sortingMode.value; // Compare resultset with expectedData. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; diff --git a/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js b/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js index 61a7a9070467..f6baba717c24 100644 --- a/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js +++ b/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js @@ -1,74 +1,74 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** 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 Places Test Code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Clint Talbert - * Marco Bonardo - * - * Alternatively, the contents of this file may be used under the terms of - * either 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 ***** */ - -// The test data for our database, note that the ordering of the results that -// will be returned by the query (the isInQuery: true objects) is IMPORTANT. -// see compareArrayToResult in head_queries.js for more info. -var testData = [ - // Normal folder - { isInQuery: true, isFolder: true, title: "Folder 1", - parentFolder: bmsvc.toolbarFolder }, - - // Read only folder - { isInQuery: false, isFolder: true, title: "Folder 2 RO", - parentFolder: bmsvc.toolbarFolder, readOnly: true } -]; - -function run_test() { - populateDB(testData); - - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); - - // Options - var options = histsvc.getNewQueryOptions(); - options.excludeQueries = true; - options.excludeReadOnlyFolders = true; - - // Results - var result = histsvc.executeQuery(query, options); - var root = result.root; - displayResultSet(root); - // The readonly folder should not be in our result set. - do_check_eq(1, root.childCount); - do_check_eq("Folder 1", root.getChild(0).title); - - root.containerOpen = false; -} +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** 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 Places Test Code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Clint Talbert + * Marco Bonardo + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +// The test data for our database, note that the ordering of the results that +// will be returned by the query (the isInQuery: true objects) is IMPORTANT. +// see compareArrayToResult in head_queries.js for more info. +var testData = [ + // Normal folder + { isInQuery: true, isFolder: true, title: "Folder 1", + parentFolder: PlacesUtils.toolbarFolderId }, + + // Read only folder + { isInQuery: false, isFolder: true, title: "Folder 2 RO", + parentFolder: PlacesUtils.toolbarFolderId, readOnly: true } +]; + +function run_test() { + populateDB(testData); + + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.toolbarFolderId], 1); + + // Options + var options = PlacesUtils.history.getNewQueryOptions(); + options.excludeQueries = true; + options.excludeReadOnlyFolders = true; + + // Results + var result = PlacesUtils.history.executeQuery(query, options); + var root = result.root; + displayResultSet(root); + // The readonly folder should not be in our result set. + do_check_eq(1, root.childCount); + do_check_eq("Folder 1", root.getChild(0).title); + + root.containerOpen = false; +} diff --git a/toolkit/components/places/tests/queries/test_onlyBookmarked.js b/toolkit/components/places/tests/queries/test_onlyBookmarked.js index b120fbfc0928..0369c421de70 100644 --- a/toolkit/components/places/tests/queries/test_onlyBookmarked.js +++ b/toolkit/components/places/tests/queries/test_onlyBookmarked.js @@ -52,16 +52,16 @@ var testData = [ // Add a bookmark that should be in the results { isBookmark: true, uri: "http://bookmarked.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.toolbarFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: true }, // Add a bookmark that should not be in the results { isBookmark: true, uri: "http://bookmarked-elsewhere.com/", - parentFolder: bmsvc.bookmarksMenuFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarksMenuFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: false }, @@ -83,16 +83,16 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.toolbarFolderId], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.queryType = options.QUERY_TYPE_HISTORY; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -111,16 +111,16 @@ function run_test() { //Add a bookmark that should show up { isBookmark: true, uri: "http://bookmarked2.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.toolbarFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: true }, //Add a bookmark that should not show up { isBookmark: true, uri: "http://bookmarked-elsewhere2.com/", - parentFolder: bmsvc.bookmarksMenuFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarksMenuFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: false } ]; @@ -150,7 +150,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); // re-query and test LOG("begin batched test"); diff --git a/toolkit/components/places/tests/queries/test_querySerialization.js b/toolkit/components/places/tests/queries/test_querySerialization.js index 0ab4d514b582..779afb1931b6 100644 --- a/toolkit/components/places/tests/queries/test_querySerialization.js +++ b/toolkit/components/places/tests/queries/test_querySerialization.js @@ -286,10 +286,10 @@ const querySwitches = [ aQuery.setFolders([], 0); }, function (aQuery, aQueryOptions) { - aQuery.setFolders([bmsvc.placesRoot], 1); + aQuery.setFolders([PlacesUtils.placesRootId], 1); }, function (aQuery, aQueryOptions) { - aQuery.setFolders([bmsvc.placesRoot, bmsvc.tagsFolder], 2); + aQuery.setFolders([PlacesUtils.placesRootId, PlacesUtils.tagsFolderId], 2); } ] }, @@ -754,8 +754,8 @@ function runQuerySequences(aHowManyLo, aHowManyHi) // ] cartProd(runs, function (runSet) { // Create a new query, apply the switches in runSet, and test it. - var query = histsvc.getNewQuery(); - var opts = histsvc.getNewQueryOptions(); + var query = PlacesUtils.history.getNewQuery(); + var opts = PlacesUtils.history.getNewQueryOptions(); for (let i = 0; i < runSet.length; i++) { runSet[i](query, opts); } @@ -793,13 +793,13 @@ function runQuerySequences(aHowManyLo, aHowManyHi) */ function serializeDeserialize(aQueryArr, aQueryOptions) { - var queryStr = histsvc.queriesToQueryString(aQueryArr, - aQueryArr.length, - aQueryOptions); + var queryStr = PlacesUtils.history.queriesToQueryString(aQueryArr, + aQueryArr.length, + aQueryOptions); print(" " + queryStr); var queryArr2 = {}; var opts2 = {}; - histsvc.queryStringToQueries(queryStr, queryArr2, {}, opts2); + PlacesUtils.history.queryStringToQueries(queryStr, queryArr2, {}, opts2); queryArr2 = queryArr2.value; opts2 = opts2.value; diff --git a/toolkit/components/places/tests/queries/test_redirectsMode.js b/toolkit/components/places/tests/queries/test_redirectsMode.js index 45063e6351ca..5a5ab41dc076 100644 --- a/toolkit/components/places/tests/queries/test_redirectsMode.js +++ b/toolkit/components/places/tests/queries/test_redirectsMode.js @@ -109,8 +109,8 @@ function check_results_callback(aSequence) { } // Create a new query with required options. - let query = histsvc.getNewQuery(); - let options = histsvc.getNewQueryOptions(); + let query = PlacesUtils.history.getNewQuery(); + let options = PlacesUtils.history.getNewQueryOptions(); options.includeHidden = includeHidden; options.redirectsMode = redirectsMode; options.sortingMode = sortingMode; @@ -118,7 +118,7 @@ function check_results_callback(aSequence) { options.maxResults = maxResults; // Compare resultset with expectedData. - let result = histsvc.executeQuery(query, options); + let result = PlacesUtils.history.executeQuery(query, options); let root = result.root; root.containerOpen = true; compareArrayToResult(expectedData, root); @@ -212,7 +212,7 @@ function cartProd(aSequences, aCallback) */ function add_visits_to_database() { // Clean up the database. - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); // We don't really bother on this, but we need a time to add visits. @@ -271,8 +271,8 @@ function add_visits_to_database() { // Add an unvisited bookmark in the database, it should never appear. visits.push({ isBookmark: true, uri: "http://unvisited.bookmark.com/", - parentFolder: bmsvc.bookmarksMenuFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarksMenuFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "Unvisited Bookmark", isInQuery: false }); @@ -302,6 +302,6 @@ function run_test() { check_results_callback); // Clean up so we can't pollute next tests. - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); } diff --git a/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js b/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js index 939806d618e2..e50b09f75658 100644 --- a/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js +++ b/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js @@ -72,10 +72,10 @@ var testData = [ function getIdForTag(aTagName) { var id = -1; - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.tagsFolder], 1); - var options = histsvc.getNewQueryOptions(); - var root = histsvc.executeQuery(query, options).root; + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.tagsFolderId], 1); + var options = PlacesUtils.history.getNewQueryOptions(); + var root = PlacesUtils.history.executeQuery(query, options).root; root.containerOpen = true; var cc = root.childCount; do_check_eq(root.childCount, 2); @@ -100,12 +100,12 @@ function run_test() { let tagId = getIdForTag("bugzilla"); do_check_true(tagId > 0); - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.resultType = options.RESULTS_AS_TAG_CONTENTS; - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.setFolders([tagId], 1); - var root = histsvc.executeQuery(query, options).root; + var root = PlacesUtils.history.executeQuery(query, options).root; root.containerOpen = true; displayResultSet(root); @@ -148,13 +148,13 @@ function run_test() { populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_false(isInResult({uri: "http://fooz.com/"}, root)); do_check_true(isInResult({uri: "http://foo.com/changeme2.html"}, root)); // Test removing a tag updates us. LOG("Delete item outside of batch"); - tagssvc.untagURI(uri("http://foo.com/changeme2.html"), ["bugzilla"]); + PlacesUtils.tagging.untagURI(uri("http://foo.com/changeme2.html"), ["bugzilla"]); do_check_false(isInResult({uri: "http://foo.com/changeme2.html"}, root)); root.containerOpen = false; diff --git a/toolkit/components/places/tests/queries/test_results-as-visit.js b/toolkit/components/places/tests/queries/test_results-as-visit.js index 80df4049847d..ab61ebfbf2ca 100644 --- a/toolkit/components/places/tests/queries/test_results-as-visit.js +++ b/toolkit/components/places/tests/queries/test_results-as-visit.js @@ -66,17 +66,17 @@ function createTestData() { function run_test() { createTestData(); populateDB(testData); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.searchTerms = "moz"; query.minVisits = 2; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_VISITCOUNT_ASCENDING; options.resultType = options.RESULTS_AS_VISIT; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -127,7 +127,7 @@ function createTestData() { populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_false(isInResult({uri: "http://foo.mail.com/changeme1.html"}, root)); do_check_true(isInResult({uri: "http://foo.mail.com/changeme3.html"}, root)); diff --git a/toolkit/components/places/tests/queries/test_searchterms-domain.js b/toolkit/components/places/tests/queries/test_searchterms-domain.js index ed6fe5f45f07..413d6a67d48d 100644 --- a/toolkit/components/places/tests/queries/test_searchterms-domain.js +++ b/toolkit/components/places/tests/queries/test_searchterms-domain.js @@ -53,7 +53,7 @@ // Test subdomain included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "amozzie", isRedirect: true, uri: "http://mail.foo.com/redirect", lastVisit: old, - referrer: "http://myreferrer.com", transType: histsvc.TRANSITION_LINK}, + referrer: "http://myreferrer.com", transType: PlacesUtils.history.TRANSITION_LINK}, // Test subdomain inclued, search term at end {isInQuery: true, isVisit: true, isDetails: true, @@ -89,18 +89,18 @@ */ function run_test() { populateDB(testData); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.searchTerms = "moz"; query.domain = "foo.com"; query.domainIsHost = false; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_DATE_ASCENDING; options.resultType = options.RESULTS_AS_URI; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -116,7 +116,7 @@ function run_test() { // Add to the query set LOG("Adding item to query") var change1 = [{isVisit: true, isDetails: true, uri: "http://foo.com/added.htm", - title: "moz", transType: histsvc.TRANSITION_LINK}]; + title: "moz", transType: PlacesUtils.history.TRANSITION_LINK}]; populateDB(change1); do_check_true(isInResult(change1, root)); @@ -140,7 +140,7 @@ function run_test() { populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_true(isInResult({uri: "http://foo.com/changeme2.htm"}, root)); do_check_true(isInResult({uri: "http://mail.foo.com/yiihah"}, root)); do_check_false(isInResult({uri: "ftp://foo.com/ftp"}, root)); diff --git a/toolkit/components/places/tests/queries/test_searchterms-uri.js b/toolkit/components/places/tests/queries/test_searchterms-uri.js index 5481f560e2dc..90368a379e82 100644 --- a/toolkit/components/places/tests/queries/test_searchterms-uri.js +++ b/toolkit/components/places/tests/queries/test_searchterms-uri.js @@ -48,7 +48,7 @@ // Test subdomain included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "amozzie", isRedirect: true, uri: "http://foo.com/redirect", lastVisit: old, - referrer: "http://myreferrer.com", transType: histsvc.TRANSITION_LINK}, + referrer: "http://myreferrer.com", transType: PlacesUtils.history.TRANSITION_LINK}, // Test www. style URI is included, with a tag {isInQuery: true, isVisit: true, isDetails: true, isTag: true, @@ -85,18 +85,18 @@ */ function run_test() { populateDB(testData); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.searchTerms = "moz"; query.uri = uri("http://foo.com"); query.uriIsPrefix = true; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_DATE_ASCENDING; options.resultType = options.RESULTS_AS_URI; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -112,7 +112,7 @@ // Add to the query set LOG("Adding item to query") var change1 = [{isVisit: true, isDetails: true, uri: "http://foo.com/added.htm", - title: "moz", transType: histsvc.TRANSITION_LINK}]; + title: "moz", transType: PlacesUtils.history.TRANSITION_LINK}]; populateDB(change1); do_check_true(isInResult(change1, root)); @@ -137,7 +137,7 @@ populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_true(isInResult({uri: "http://foo.com/changeme2.htm"}, root)); do_check_true(isInResult({uri: "http://foo.com/yiihah"}, root)); do_check_false(isInResult({uri: "http://foo.com/redirect"}, root)); diff --git a/toolkit/components/places/tests/queries/test_sorting.js b/toolkit/components/places/tests/queries/test_sorting.js index cc9e251da8a1..f06db6760dcf 100644 --- a/toolkit/components/places/tests/queries/test_sorting.js +++ b/toolkit/components/places/tests/queries/test_sorting.js @@ -50,24 +50,24 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y", keyword: "b", isInQuery: true }, { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "z", keyword: "a", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "x", keyword: "c", isInQuery: true }, @@ -81,16 +81,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -113,30 +113,30 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y", isInQuery: true }, { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "z", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "x", isInQuery: true }, // if titles are equal, should fall back to URI { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y", isInQuery: true }, ]; @@ -154,16 +154,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -190,7 +190,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, uri: "http://example.com/c1", lastVisit: timeInMicroseconds - 2, @@ -200,7 +200,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, uri: "http://example.com/a", lastVisit: timeInMicroseconds - 1, @@ -210,7 +210,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, uri: "http://example.com/b", lastVisit: timeInMicroseconds - 3, @@ -221,7 +221,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, uri: "http://example.com/c2", lastVisit: timeInMicroseconds - 2, @@ -232,7 +232,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, uri: "http://example.com/c2", lastVisit: timeInMicroseconds - 2, @@ -254,16 +254,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -291,21 +291,21 @@ tests.push({ isDetails: true, lastVisit: timeInMicroseconds, uri: "http://example.com/b", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, title: "y", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, title: "x", isInQuery: true }, { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, title: "z", isInQuery: true }, @@ -315,14 +315,14 @@ tests.push({ isDetails: true, lastVisit: timeInMicroseconds + 1, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, title: "x", isInQuery: true }, // if no URI (e.g., node is a folder), should fall back to title { isFolder: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, title: "a", isInQuery: true }, @@ -332,14 +332,14 @@ tests.push({ isDetails: true, lastVisit: timeInMicroseconds + 1, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 5, title: "x", isInQuery: true }, // if no URI and titles are equal, should fall back to bookmark index { isFolder: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 6, title: "a", isInQuery: true }, @@ -361,15 +361,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -397,7 +397,7 @@ tests.push({ uri: "http://example.com/a", lastVisit: timeInMicroseconds, title: "z", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, isInQuery: true }, @@ -405,7 +405,7 @@ tests.push({ uri: "http://example.com/c", lastVisit: timeInMicroseconds, title: "x", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, isInQuery: true }, @@ -413,7 +413,7 @@ tests.push({ uri: "http://example.com/b1", lastVisit: timeInMicroseconds, title: "y1", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, isInQuery: true }, @@ -422,7 +422,7 @@ tests.push({ uri: "http://example.com/b2", lastVisit: timeInMicroseconds + 1, title: "y2a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, isInQuery: true }, @@ -431,7 +431,7 @@ tests.push({ uri: "http://example.com/b2", lastVisit: timeInMicroseconds + 1, title: "y2b", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, isInQuery: true }, ]; @@ -447,36 +447,36 @@ tests.push({ // This function in head_queries.js creates our database with the above data populateDB(this._unsortedData); // add visits to increase visit count - histsvc.addVisit(uri("http://example.com/a"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/a"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); }, check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -501,24 +501,24 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "z", keyword: "a", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "x", keyword: "c", isInQuery: true }, { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y9", keyword: "b", isInQuery: true }, @@ -526,8 +526,8 @@ tests.push({ // without a keyword, should fall back to title { isBookmark: true, uri: "http://example.com/null2", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "null8", keyword: null, isInQuery: true }, @@ -535,8 +535,8 @@ tests.push({ // without a keyword, should fall back to title { isBookmark: true, uri: "http://example.com/null1", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "null9", keyword: null, isInQuery: true }, @@ -544,8 +544,8 @@ tests.push({ // if keywords are equal, should fall back to title { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y8", keyword: "b", isInQuery: true }, @@ -566,16 +566,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -601,7 +601,7 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, title: "y1", dateAdded: timeInMicroseconds -1, @@ -609,7 +609,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, title: "z", dateAdded: timeInMicroseconds - 2, @@ -617,7 +617,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, title: "x", dateAdded: timeInMicroseconds, @@ -626,7 +626,7 @@ tests.push({ // if dateAddeds are equal, should fall back to title { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, title: "y2", dateAdded: timeInMicroseconds - 1, @@ -635,7 +635,7 @@ tests.push({ // if dateAddeds and titles are equal, should fall back to bookmark index { isBookmark: true, uri: "http://example.com/b3", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, title: "y3", dateAdded: timeInMicroseconds - 1, @@ -656,16 +656,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -691,7 +691,7 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, title: "y1", lastModified: timeInMicroseconds -1, @@ -699,7 +699,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, title: "z", lastModified: timeInMicroseconds - 2, @@ -707,7 +707,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, title: "x", lastModified: timeInMicroseconds, @@ -716,7 +716,7 @@ tests.push({ // if lastModifieds are equal, should fall back to title { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, title: "y2", lastModified: timeInMicroseconds - 1, @@ -726,7 +726,7 @@ tests.push({ // index { isBookmark: true, uri: "http://example.com/b3", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, title: "y3", lastModified: timeInMicroseconds - 1, @@ -747,16 +747,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -781,8 +781,8 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://url2.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title x", isTag: true, tagArray: ["x", "y", "z"], @@ -790,8 +790,8 @@ tests.push({ { isBookmark: true, uri: "http://url1a.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title y1", isTag: true, tagArray: ["a", "b"], @@ -799,15 +799,15 @@ tests.push({ { isBookmark: true, uri: "http://url3a.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title w1", isInQuery: true }, { isBookmark: true, uri: "http://url0.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title z", isTag: true, tagArray: ["a", "y", "z"], @@ -816,8 +816,8 @@ tests.push({ // if tags are equal, should fall back to title { isBookmark: true, uri: "http://url1b.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title y2", isTag: true, tagArray: ["b", "a"], @@ -826,8 +826,8 @@ tests.push({ // if tags are equal, should fall back to title { isBookmark: true, uri: "http://url3b.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title w2", isInQuery: true }, ]; @@ -847,16 +847,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -944,15 +944,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1026,15 +1026,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1108,15 +1108,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1190,15 +1190,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1216,7 +1216,7 @@ tests.push({ function prepare_for_next_test() { // Execute cleanup tasks - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); } diff --git a/toolkit/components/places/tests/queries/test_tags.js b/toolkit/components/places/tests/queries/test_tags.js index 774e0702571b..f16614f824f6 100644 --- a/toolkit/components/places/tests/queries/test_tags.js +++ b/toolkit/components/places/tests/queries/test_tags.js @@ -71,14 +71,14 @@ var gTests = [ desc: "Invalid calls to tags setter should fail", run: function () { try { - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.tags = null; do_throw(" Passing null to SetTags should fail"); } catch (exc) {} try { - query = histsvc.getNewQuery(); + query = PlacesUtils.history.getNewQuery(); query.tags = "this should not work"; do_throw(" Passing a string to SetTags should fail"); } @@ -126,7 +126,7 @@ var gTests = [ var str = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); str.data = "foo"; - query = histsvc.getNewQuery(); + query = PlacesUtils.history.getNewQuery(); query.tags = str; do_throw(" Passing nsISupportsString to SetTags should fail"); } @@ -377,32 +377,32 @@ var gTests = [ let nsiuri = uri(pURI); addVisit(nsiuri); if (tags) - tagssvc.tagURI(nsiuri, tags); + PlacesUtils.tagging.tagURI(nsiuri, tags); } print(' Querying for "foo" should match only /2 and /3'); var [query, opts] = makeQuery(["foo"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bar" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bar"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bogus" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bogus"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "baz" should match only /3'); [query, opts] = makeQuery(["foo", "baz"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/3"]); print(' Querying for "bogus" should match all'); [query, opts] = makeQuery(["bogus"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/1", "http://example.com/2", "http://example.com/3"]); @@ -411,7 +411,7 @@ var gTests = [ for (let [pURI, tags] in Iterator(urisAndTags)) { let nsiuri = uri(pURI); if (tags) - tagssvc.untagURI(nsiuri, tags); + PlacesUtils.tagging.untagURI(nsiuri, tags); } cleanDatabase(); } @@ -431,37 +431,37 @@ var gTests = [ let nsiuri = uri(pURI); addBookmark(nsiuri); if (tags) - tagssvc.tagURI(nsiuri, tags); + PlacesUtils.tagging.tagURI(nsiuri, tags); } print(' Querying for "foo" should match only /2 and /3'); var [query, opts] = makeQuery(["foo"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bar" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bar"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bogus" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bogus"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "baz" should match only /3'); [query, opts] = makeQuery(["foo", "baz"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/3"]); print(' Querying for "bogus" should match all'); [query, opts] = makeQuery(["bogus"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/1", "http://example.com/2", "http://example.com/3"]); @@ -470,7 +470,7 @@ var gTests = [ for (let [pURI, tags] in Iterator(urisAndTags)) { let nsiuri = uri(pURI); if (tags) - tagssvc.untagURI(nsiuri, tags); + PlacesUtils.tagging.untagURI(nsiuri, tags); } cleanDatabase(); } @@ -484,26 +484,26 @@ var gTests = [ print(" Add bookmark and tag it normally"); addBookmark(TEST_URI); - tagssvc.tagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.tagURI(TEST_URI, [tagName]); print(" Manually create tag folder with same name as tag and insert " + "bookmark"); - var dupTagId = bmsvc.createFolder(bmsvc.tagsFolder, - tagName, - bmsvc.DEFAULT_INDEX); + var dupTagId = PlacesUtils.bookmarks.createFolder(PlacesUtils.tagsFolderId, + tagName, + Ci.nsINavBookmarksService.DEFAULT_INDEX); do_check_true(dupTagId > 0); - var bmId = bmsvc.insertBookmark(dupTagId, - TEST_URI, - bmsvc.DEFAULT_INDEX, - "title"); + var bmId = PlacesUtils.bookmarks.insertBookmark(dupTagId, + TEST_URI, + Ci.nsINavBookmarksService.DEFAULT_INDEX, + "title"); do_check_true(bmId > 0); print(" Querying for tag should match URI"); var [query, opts] = makeQuery([tagName]); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, [TEST_URI.spec]); + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, [TEST_URI.spec]); - tagssvc.untagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.untagURI(TEST_URI, [tagName]); cleanDatabase(); } }, @@ -516,20 +516,20 @@ var gTests = [ print(" Add bookmark and tag it"); addBookmark(TEST_URI); - tagssvc.tagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.tagURI(TEST_URI, [tagName]); print(" Create folder with same name as tag"); - var folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder, - tagName, - bmsvc.DEFAULT_INDEX); + var folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, + tagName, + Ci.nsINavBookmarksService.DEFAULT_INDEX); do_check_true(folderId > 0); print(" Querying for tag should match URI"); var [query, opts] = makeQuery([tagName]); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, [TEST_URI.spec]); + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, [TEST_URI.spec]); - tagssvc.untagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.untagURI(TEST_URI, [tagName]); cleanDatabase(); } }, @@ -554,53 +554,53 @@ var gTests = [ let nsiuri = uri(pURI); addVisit(nsiuri); if (tags) - tagssvc.tagURI(nsiuri, tags); + PlacesUtils.tagging.tagURI(nsiuri, tags); } print(" Query for /1 OR query for /2 should match both /1 and /2"); var [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); var [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"]); - var root = histsvc.executeQueries([query1, query2], 2, opts).root; + var root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); print(" Query for /1 OR query on bogus tag should match only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(["bogus"]); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); print(" Query for /1 OR query for /1 should match only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(urisAndTags["http://example.com/1"]); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); print(" Query for /1 with tagsAreNot OR query for /2 with tagsAreNot " + "should match both /1 and /2"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"], true); [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"], true); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); print(" Query for /1 OR query for /2 with tagsAreNot should match " + "only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"], true); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); print(" Query for /1 OR query for /1 with tagsAreNot should match " + "both URIs"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(urisAndTags["http://example.com/1"], true); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); // Clean up. for (let [pURI, tags] in Iterator(urisAndTags)) { let nsiuri = uri(pURI); if (tags) - tagssvc.untagURI(nsiuri, tags); + PlacesUtils.tagging.untagURI(nsiuri, tags); } cleanDatabase(); } @@ -623,10 +623,10 @@ const TEST_URI = uri("http://example.com/"); * URI of the page (an nsIURI) */ function addBookmark(aURI) { - var bmId = bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder, - aURI, - bmsvc.DEFAULT_INDEX, - aURI.spec); + var bmId = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + aURI, + Ci.nsINavBookmarksService.DEFAULT_INDEX, + aURI.spec); print(" Sanity check: insertBookmark should not fail"); do_check_true(bmId > 0); } @@ -638,12 +638,12 @@ function addBookmark(aURI) { * URI of the page (an nsIURI) */ function addVisit(aURI) { - var visitId = histsvc.addVisit(aURI, - Date.now() * 1000, - null, - histsvc.TRANSITION_LINK, - false, - 0); + var visitId = PlacesUtils.history.addVisit(aURI, + Date.now() * 1000, + null, + Ci.nsINavHistoryService.TRANSITION_LINK, + false, + 0); print(" Sanity check: addVisit should not fail"); do_check_true(visitId > 0); } @@ -652,7 +652,7 @@ function addVisit(aURI) { * Removes all pages from history and bookmarks. */ function cleanDatabase() { - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); } @@ -688,9 +688,9 @@ function checkQueryURI(aTags, aTagsAreNot) { */ function doWithBookmark(aTags, aCallback) { addBookmark(TEST_URI); - tagssvc.tagURI(TEST_URI, aTags); + PlacesUtils.tagging.tagURI(TEST_URI, aTags); aCallback(TEST_URI); - tagssvc.untagURI(TEST_URI, aTags); + PlacesUtils.tagging.untagURI(TEST_URI, aTags); cleanDatabase(); } @@ -706,9 +706,9 @@ function doWithBookmark(aTags, aCallback) { */ function doWithVisit(aTags, aCallback) { addVisit(TEST_URI); - tagssvc.tagURI(TEST_URI, aTags); + PlacesUtils.tagging.tagURI(TEST_URI, aTags); aCallback(TEST_URI); - tagssvc.untagURI(TEST_URI, aTags); + PlacesUtils.tagging.untagURI(TEST_URI, aTags); cleanDatabase(); } @@ -740,7 +740,7 @@ function encodeTag(aTag) { * Array of URIs (as strings) that aResultRoot should contain */ function executeAndCheckQueryResults(aQuery, aQueryOpts, aExpectedURIs) { - var root = histsvc.executeQuery(aQuery, aQueryOpts).root; + var root = PlacesUtils.history.executeQuery(aQuery, aQueryOpts).root; root.containerOpen = true; queryResultsAre(root, aExpectedURIs); root.containerOpen = false; @@ -765,7 +765,7 @@ function makeQuery(aTags, aTagsAreNot) { "without calling setTags() at all") + " and with tagsAreNot=" + aTagsAreNot); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.tagsAreNot = aTagsAreNot; if (aTags) { query.tags = aTags; @@ -784,7 +784,7 @@ function makeQuery(aTags, aTagsAreNot) { do_check_eq(query.tags.length, expCount); do_check_eq(query.tagsAreNot, aTagsAreNot); - return [query, histsvc.getNewQueryOptions()]; + return [query, PlacesUtils.history.getNewQueryOptions()]; } /** @@ -818,7 +818,7 @@ function queryResultsAre(aResultRoot, aExpectedURIs) { * @return The query's URI */ function queryURI(aQuery, aQueryOpts) { - return histsvc.queriesToQueryString([aQuery], 1, aQueryOpts); + return PlacesUtils.history.queriesToQueryString([aQuery], 1, aQueryOpts); } /** diff --git a/toolkit/components/places/tests/sync/head_sync.js b/toolkit/components/places/tests/sync/head_sync.js index 771a1435f38b..ceeb6211163a 100644 --- a/toolkit/components/places/tests/sync/head_sync.js +++ b/toolkit/components/places/tests/sync/head_sync.js @@ -39,120 +39,21 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -// If there's no location registered for the profile direcotry, register one now. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var profileDir = null; -try { - profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile); -} catch (e) {} -if (!profileDir) { - // Register our own provider for the profile directory. - // It will simply return the current directory. - var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_USER_PROFILE_50_DIR) { - return dirSvc.get("CurProcD", Ci.nsIFile); - } - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("CurProcD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); -} +// Put any other stuff relative to this test folder below. -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = DBConn() - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} /** * Function tests to see if the place associated with the bookmark with id @@ -170,8 +71,7 @@ function dump_table(aName) */ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFinish) { - let db = DBConn(); - let stmt = db.createStatement( + let stmt = DBConn().createStatement( "SELECT moz_places.url " + "FROM moz_bookmarks INNER JOIN moz_places " + "ON moz_bookmarks.fk = moz_places.id " + @@ -194,6 +94,7 @@ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFini do_test_finished(); } + /** * Function tests to see if the place associated with the visit with id aVisitId * has the uri aExpectedURI. The event will call do_test_finished() if aFinish is @@ -210,8 +111,7 @@ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFini */ function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) { - let db = DBConn(); - let stmt = db.createStatement( + let stmt = DBConn().createStatement( "SELECT moz_places.url " + "FROM moz_historyvisits INNER JOIN moz_places " + "ON moz_historyvisits.place_id = moz_places.id " + @@ -234,50 +134,3 @@ function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) do_test_finished(); } -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// Simulates a Places shutdown. -function shutdownPlaces() -{ - const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown"; - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsIObserver); - hs.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let expire = Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsIObserver); - expire.observe(null, TOPIC_XPCOM_SHUTDOWN, null); -} diff --git a/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js b/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js index d0cc6934fcfb..e805817fdb49 100644 --- a/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js +++ b/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js @@ -110,13 +110,13 @@ function check_results() { do_test_finished(); } - if (hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection.connectionReady) { + if (PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) + .DBConnection.connectionReady) { do_timeout(POLLING_TIMEOUT_MS, check_results); return; } let dbConn = DBConn(); - do_check_neq(dbConn, null); do_check_true(dbConn.connectionReady); // Check that frecency for not cleared items (bookmarks) has been @@ -127,14 +127,14 @@ function check_results() { do_check_false(stmt.executeStep()); stmt.finalize(); - stmt = DBConn().createStatement( + stmt = dbConn.createStatement( "SELECT h.id FROM moz_places h WHERE h.frecency = -2 " + "AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1"); do_check_true(stmt.executeStep()); stmt.finalize(); // Check that all visit_counts have been brought to 0 - stmt = DBConn().createStatement( + stmt = dbConn.createStatement( "SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1"); do_check_false(stmt.executeStep()); stmt.finalize(); diff --git a/toolkit/components/places/tests/unit/head_bookmarks.js b/toolkit/components/places/tests/unit/head_bookmarks.js index b1b444f90923..2228f7347197 100644 --- a/toolkit/components/places/tests/unit/head_bookmarks.js +++ b/toolkit/components/places/tests/unit/head_bookmarks.js @@ -12,16 +12,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Places. + * The Original Code is Places Unit Tests. * - * The Initial Developer of the Original Code is - * Google Inc. - * Portions created by the Initial Developer are Copyright (C) 2005 + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Brian Ryner - * Dietrich Ayala + * Marco Bonardo * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,298 +35,17 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -do_get_profile(); - -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("ProfD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -/* - * Reads the data from the specified nsIFile, and returns an array of bytes. - */ -function readFileData(aFile) { - var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - // init the stream as RD_ONLY, -1 == default permissions. - inputStream.init(aFile, 0x01, -1, null); - var size = inputStream.available(); - - // use a binary input stream to grab the bytes. - var bis = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(inputStream); - - var bytes = bis.readByteArray(size); - - if (size != bytes.length) - throw "Didn't read expected number of bytes"; - - return bytes; -} - -/* - * Compares two arrays, and returns true if they are equal. - */ -function compareArrays(aArray1, aArray2) { - if (aArray1.length != aArray2.length) { - print("compareArrays: array lengths differ\n"); - return false; - } - - for (var i = 0; i < aArray1.length; i++) { - if (aArray1[i] != aArray2[i]) { - print("compareArrays: arrays differ at index " + i + ": " + - "(" + aArray1[i] + ") != (" + aArray2[i] +")\n"); - return false; - } - } - - return true; -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Sets title synchronously for a page in moz_places synchronously. - * History.SetPageTitle uses LAZY_ADD so we can't rely on it. - * - * @param aURI - * An nsIURI to set the title for. - * @param aTitle - * The title to set the page to. - * @throws if the page is not found in the database. - * - * @note this function only exists because we have no API to do this. It should - * be added in bug 421897. - */ -function setPageTitle(aURI, aTitle) { - let dbConn = DBConn(); - // Check that the page exists. - let stmt = dbConn.createStatement( - "SELECT id FROM moz_places_view WHERE url = :url"); - stmt.params.url = aURI.spec; - try { - if (!stmt.executeStep()) { - do_throw("Unable to find page " + aURIString); - return; - } - } - finally { - stmt.finalize(); - } - - // Update the title - stmt = dbConn.createStatement( - "UPDATE moz_places_view SET title = :title WHERE url = :url"); - stmt.params.title = aTitle; - stmt.params.url = aURI.spec; - try { - stmt.execute(); - } - finally { - stmt.finalize(); - } -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let observer = { - observe: function(aSubject, aTopic, aData) { - os.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } - }; - os.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages(); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_multi_word_tags.js", - "test_removeVisitsByTimeframe.js", - "test_utils_getURLsForContainerNode.js", - "test_exclude_livemarks.js", - "test_402799.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} +// Put any other stuff relative to this test folder below. diff --git a/toolkit/components/places/tests/unit/test_412132.js b/toolkit/components/places/tests/unit/test_412132.js index ae303a348c75..8a73511e5be5 100644 --- a/toolkit/components/places/tests/unit/test_412132.js +++ b/toolkit/components/places/tests/unit/test_412132.js @@ -303,14 +303,15 @@ function getFrecency(url) return frecency; } -function prepTest(testIndex, testName, callback) +function prepTest(testName, callback) { - print("Test " + testIndex + ": " + testName); + print("Test: " + testName); waitForClearHistory(function() { dbConn.executeSimpleSQL("DELETE FROM moz_places_view"); dbConn.executeSimpleSQL("DELETE FROM moz_bookmarks WHERE id > " + defaultBookmarksMaxId); callback(); + runNextTest(); }); } @@ -328,6 +329,7 @@ function visit(uri) function run_test() { + do_test_pending(); var stmt; dbConn = @@ -341,8 +343,16 @@ function run_test() stmt.finalize(); do_check_true(defaultBookmarksMaxId > 0); - for (let i= 0; i < tests.length; i++) - { - prepTest(i, tests[i].desc, tests[i].run); + runNextTest(); +} + +let currentTest; +function runNextTest() { + if (tests.length) { + currentTest = tests.shift(); + prepTest(currentTest.desc, currentTest.run); + } + else { + do_test_finished(); } } diff --git a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js index 5160cf0f60bf..127c80108bff 100644 --- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js +++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js @@ -64,7 +64,7 @@ function checkAddSucceeded(pageURI, mimetype, data) { var favicons = [ { - uri: iosvc.newFileURI(do_get_file("favicon-normal32.png")), + uri: uri(do_get_file("favicon-normal32.png")), data: readFileData(do_get_file("favicon-normal32.png")), mimetype: "image/png" } diff --git a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js index 0d3d5bacf60e..460afec82113 100644 --- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js +++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js @@ -59,13 +59,13 @@ XPCOMUtils.defineLazyServiceGetter(this, "prefs", let favicons = [ { - uri: iosvc.newFileURI(do_get_file("favicon-normal16.png")), + uri: uri(do_get_file("favicon-normal16.png")), data: readFileData(do_get_file("favicon-normal16.png")), mimetype: "image/png", size: 286 }, { - uri: iosvc.newFileURI(do_get_file("favicon-normal32.png")), + uri: uri(do_get_file("favicon-normal32.png")), data: readFileData(do_get_file("favicon-normal32.png")), mimetype: "image/png", size: 344 @@ -154,7 +154,7 @@ let historyObserver = { do_check_true(pageURI.equals(uri("http://test4.bar/"))); // Ensure there is only one entry in favicons table. - let stmt = DBConn().createStatement( + let stmt = PlacesServices.DBConn.createStatement( "SELECT url FROM moz_favicons" ); let c = 0; @@ -178,6 +178,12 @@ let historyObserver = { let currentTest = null; function run_test() { + // Disabled till LAZY_ADD is killed, this test should be fixed, since the + // below timeout is clearly wrong due to 3s lazy timer. But fixing it right + // now would mean making it take about 12s to run. This is not acceptable. + // See bug 555519. + return; + do_test_pending(); // check that the favicon loaded correctly diff --git a/toolkit/components/places/tests/unit/test_history.js b/toolkit/components/places/tests/unit/test_history.js index f6603fe17bff..04c387a7cc89 100644 --- a/toolkit/components/places/tests/unit/test_history.js +++ b/toolkit/components/places/tests/unit/test_history.js @@ -226,7 +226,7 @@ function run_test() { // test to ensure history.dat gets deleted if all history is being cleared var file = do_get_file("history.dat"); - var histFile = dirSvc.get("ProfD", Ci.nsIFile); + var histFile = Services.dirsvc.get("ProfD", Ci.nsIFile); file.copyTo(histFile, "history.dat"); histFile.append("history.dat"); do_check_true(histFile.exists()); diff --git a/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js b/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js index 715036b34c58..339b7e57471a 100644 --- a/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js +++ b/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js @@ -69,7 +69,7 @@ if (!profileDir) { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js index 2480d4ea4660..124833ea098a 100644 --- a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js +++ b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js @@ -7,9 +7,7 @@ function cleanup_and_finish() { try { cleanup_fake_appdir(); } catch(ex) {} - let prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - prefs.clearUserPref("breakpad.reportURL"); + Services.prefs.clearUserPref("breakpad.reportURL"); gBrowser.removeTab(gBrowser.selectedTab); finish(); } @@ -135,10 +133,8 @@ function test() { crashes.sort(function(a,b) b.date - a.date); // set this pref so we can link to our test server - let prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - - prefs.setCharPref("breakpad.reportURL", "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs?id="); + Services.prefs.setCharPref("breakpad.reportURL", + "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs?id="); let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank"); let browser = gBrowser.getBrowserForTab(tab); diff --git a/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js b/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js index cef9ebb0fecb..8285808f058d 100644 --- a/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js +++ b/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js @@ -70,7 +70,7 @@ if (!profileDir) { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug510909.js b/toolkit/mozapps/extensions/test/browser/browser_bug510909.js index d3a33d3539e9..ed6629b30451 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug510909.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug510909.js @@ -5,9 +5,7 @@ var win = null; function WindowListener(url) { this.url = url; - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.addListener(this); + Services.wm.addListener(this); } WindowListener.prototype = { @@ -38,9 +36,7 @@ WindowListener.prototype = { }, onCloseWindow: function(window) { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.removeListener(this); + Services.wm.removeListener(this); }, QueryInterface: function(iid) { diff --git a/toolkit/xre/nsNativeAppSupportUnix.cpp b/toolkit/xre/nsNativeAppSupportUnix.cpp index 8aa75451133f..56b68d4f717d 100644 --- a/toolkit/xre/nsNativeAppSupportUnix.cpp +++ b/toolkit/xre/nsNativeAppSupportUnix.cpp @@ -53,18 +53,36 @@ #include "nsICommandLineRunner.h" #include "nsIWindowMediator.h" #include "nsIDOMWindowInternal.h" +#include "nsPIDOMWindow.h" +#include "nsIDocShell.h" +#include "nsIBaseWindow.h" +#include "nsIWidget.h" +#include "nsIWritablePropertyBag2.h" #include #include #include #include +#ifdef MOZ_X11 +#include +#include +#endif + #ifdef MOZ_PLATFORM_MAEMO struct DBusMessage; /* libosso.h references internals of dbus */ #include #include #include + +// These come from (maemo sdk 5+) +#define MCE_SERVICE "com.nokia.mce" +#define MCE_REQUEST_IF "com.nokia.mce.request" +#define MCE_REQUEST_PATH "/com/nokia/mce/request" +#define MCE_SIGNAL_IF "com.nokia.mce.signal" +#define MCE_DEVICE_ORIENTATION_SIG "sig_device_orientation_ind" +#define MCE_MATCH_RULE "type='signal',interface='" MCE_SIGNAL_IF "',member='" MCE_DEVICE_ORIENTATION_SIG "'" #endif #define MIN_GTK_MAJOR_VERSION 2 @@ -155,6 +173,7 @@ class nsNativeAppSupportUnix : public nsNativeAppSupportBase public: NS_IMETHOD Start(PRBool* aRetVal); NS_IMETHOD Stop(PRBool *aResult); + NS_IMETHOD Enable(); private: #ifdef MOZ_PLATFORM_MAEMO @@ -169,17 +188,118 @@ private: }; #ifdef MOZ_PLATFORM_MAEMO +static nsresult +GetMostRecentWindow(const PRUnichar* aType, nsIDOMWindowInternal** aWindow) +{ + nsCOMPtr wm = do_GetService("@mozilla.org/appshell/window-mediator;1"); + if (wm) + return wm->GetMostRecentWindow(aType, aWindow); + return NS_ERROR_FAILURE; +} + +static GtkWidget* +WidgetForDOMWindow(nsISupports *aWindow) +{ + nsCOMPtr domWindow(do_QueryInterface(aWindow)); + if (!domWindow) + return NULL; + + nsCOMPtr baseWindow = do_QueryInterface(domWindow->GetDocShell()); + if (!baseWindow) + return NULL; + + nsCOMPtr widget; + baseWindow->GetMainWidget(getter_AddRefs(widget)); + if (!widget) + return NULL; + + return (GtkWidget*)(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); +} + +static void +OssoSetWindowOrientation(PRBool aPortrait) +{ + // Tell Hildon desktop to force our window to be either portrait or landscape, + // depending on the current rotation + // NOTE: We only update the most recent top-level window so this is only + // suitable for apps with only one window. + nsCOMPtr window; + GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window)); + GtkWidget* widget = WidgetForDOMWindow(window); + if (widget && widget->window) { + GdkWindow *gdk = widget->window; + GdkAtom request = gdk_atom_intern("_HILDON_PORTRAIT_MODE_REQUEST", FALSE); + + if (aPortrait) { + gulong portrait_set = 1; + gdk_property_change(gdk, request, gdk_x11_xatom_to_atom(XA_CARDINAL), + 32, GDK_PROP_MODE_REPLACE, (const guchar *) &portrait_set, 1); + } + else { + gdk_property_delete(gdk, request); + } + } + + // Update the system info property + nsCOMPtr info = do_GetService("@mozilla.org/system-info;1"); + if (info) { + info->SetPropertyAsAString(NS_LITERAL_STRING("screen-orientation"), + aPortrait ? NS_LITERAL_STRING("portrait") : NS_LITERAL_STRING("landscape")); + } +} + +static PRBool OssoIsScreenOn(osso_context_t* ctx) +{ + osso_return_t rv; + osso_rpc_t ret; + PRBool result = PR_FALSE; + + rv = osso_rpc_run_system(ctx, MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF, + "get_display_status", &ret, DBUS_TYPE_INVALID); + if (rv == OSSO_OK) { + if (strcmp(ret.value.s, "on") == 0) + result = PR_TRUE; + + osso_rpc_free_val(&ret); + } + return result; +} + +static void OssoRequestAccelerometer(osso_context_t *ctx, PRBool aEnabled) +{ + osso_return_t rv; + osso_rpc_t ret; + + rv = osso_rpc_run_system(ctx, + MCE_SERVICE, + MCE_REQUEST_PATH, MCE_REQUEST_IF, + aEnabled ? "req_accelerometer_enable" : "req_accelerometer_disable", + aEnabled ? &ret : NULL, + DBUS_TYPE_INVALID); + + // Orientation might changed while the accelerometer was off, so let's update + // the window's orientation + if (rv == OSSO_OK && aEnabled) { + OssoSetWindowOrientation(strcmp(ret.value.s, "portrait") == 0); + osso_rpc_free_val(&ret); + } +} static void OssoDisplayCallback(osso_display_state_t state, gpointer data) { nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1"); if (!os) return; - - if (state == OSSO_DISPLAY_ON) + + osso_context_t* context = (osso_context_t*) data; + + if (state == OSSO_DISPLAY_ON) { os->NotifyObservers(nsnull, "system-display-on", nsnull); - else + OssoRequestAccelerometer(context, PR_TRUE); + } else { os->NotifyObservers(nsnull, "system-display-dimmed-or-off", nsnull); + OssoRequestAccelerometer(context, PR_FALSE); + } } static void OssoHardwareCallback(osso_hw_state_t *state, gpointer data) @@ -226,13 +346,11 @@ OssoDbusCallback(const gchar *interface, const gchar *method, // The "top_application" method just wants us to focus the top-most window. if (!strcmp("top_application", method)) { - nsCOMPtr wm = do_GetService("@mozilla.org/appshell/window-mediator;1"); - nsCOMPtr window; - wm->GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window)); - if (window) { + GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window)); + if (window) window->Focus(); - } + return OSSO_OK; } @@ -285,6 +403,21 @@ OssoDbusCallback(const gchar *interface, const gchar *method, return OSSO_OK; } +static DBusHandlerResult +OssoModeControlCallback(DBusConnection *con, DBusMessage *msg, gpointer data) +{ + if (dbus_message_is_signal(msg, MCE_SIGNAL_IF, MCE_DEVICE_ORIENTATION_SIG)) { + DBusMessageIter iter; + if (dbus_message_iter_init(msg, &iter)) { + const gchar *mode = NULL; + dbus_message_iter_get_basic(&iter, &mode); + + OssoSetWindowOrientation(strcmp(mode, "portrait") == 0); + } + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + #endif NS_IMETHODIMP @@ -323,7 +456,7 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal) system will happily kill your process. */ nsCAutoString applicationName; - if(gAppData->vendor) { + if (gAppData->vendor) { applicationName.Append(gAppData->vendor); applicationName.Append("."); } @@ -341,8 +474,13 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal) } osso_hw_set_event_cb(m_osso_context, nsnull, OssoHardwareCallback, &m_hw_state); - osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, nsnull); + osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, m_osso_context); osso_rpc_set_default_cb_f(m_osso_context, OssoDbusCallback, nsnull); + + // Setup an MCE callback to monitor orientation + DBusConnection *connnection = (DBusConnection*)osso_get_sys_dbus_connection(m_osso_context); + dbus_bus_add_match(connnection, MCE_MATCH_RULE, nsnull); + dbus_connection_add_filter(connnection, OssoModeControlCallback, nsnull, nsnull); #endif *aRetVal = PR_TRUE; @@ -455,6 +593,13 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult) #ifdef MOZ_PLATFORM_MAEMO if (m_osso_context) { + // Disable the accelerometer when closing + OssoRequestAccelerometer(m_osso_context, PR_FALSE); + + // Remove the MCE callback filter + DBusConnection *connnection = (DBusConnection*)osso_get_sys_dbus_connection(m_osso_context); + dbus_connection_remove_filter(connnection, OssoModeControlCallback, nsnull); + osso_hw_unset_event_cb(m_osso_context, nsnull); osso_rpc_unset_default_cb_f(m_osso_context, OssoDbusCallback, nsnull); osso_deinitialize(m_osso_context); @@ -464,6 +609,17 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult) return NS_OK; } +NS_IMETHODIMP +nsNativeAppSupportUnix::Enable() +{ +#ifdef MOZ_PLATFORM_MAEMO + // Enable the accelerometer for orientation support + if (OssoIsScreenOn(m_osso_context)) + OssoRequestAccelerometer(m_osso_context, PR_TRUE); +#endif + return NS_OK; +} + nsresult NS_CreateNativeAppSupport(nsINativeAppSupport **aResult) { diff --git a/toolkit/xre/nsNativeAppSupportWin.cpp b/toolkit/xre/nsNativeAppSupportWin.cpp index 6ed9a16c6a2d..707028373288 100644 --- a/toolkit/xre/nsNativeAppSupportWin.cpp +++ b/toolkit/xre/nsNativeAppSupportWin.cpp @@ -343,7 +343,6 @@ private: static void ActivateLastWindow(); static nsresult OpenWindow( const char *urlstr, const char *args ); static nsresult OpenBrowserWindow(); - static nsresult ReParent( nsISupports *window, HWND newParent ); static void SetupSysTrayIcon(); static void RemoveSysTrayIcon(); diff --git a/tools/trace-malloc/spacecategory.c b/tools/trace-malloc/spacecategory.c index c71b7b27addb..bac61a829ef8 100644 --- a/tools/trace-malloc/spacecategory.c +++ b/tools/trace-malloc/spacecategory.c @@ -122,7 +122,7 @@ AddChild(STCategoryNode * parent, STCategoryNode * child) } int -ReParent(STCategoryNode * parent, STCategoryNode * child) +Reparent(STCategoryNode * parent, STCategoryNode * child) { PRUint32 i; @@ -312,7 +312,7 @@ ProcessCategoryParentRule(STCategoryRule * parentRule, STCategoryNode * root, ** we would have created it as the child of root. Now we need to ** remove it from root's child list and add it into this node */ - ReParent(node, child); + Reparent(node, child); } } diff --git a/widget/src/gtk2/nsLookAndFeel.cpp b/widget/src/gtk2/nsLookAndFeel.cpp index ddd32deefb6d..35e2dd262f85 100644 --- a/widget/src/gtk2/nsLookAndFeel.cpp +++ b/widget/src/gtk2/nsLookAndFeel.cpp @@ -747,6 +747,7 @@ nsLookAndFeel::InitLookAndFeel() GtkWidget *treeView = gtk_tree_view_new(); GtkWidget *linkButton = gtk_link_button_new("http://example.com/"); GtkWidget *menuBar = gtk_menu_bar_new(); + GtkWidget *entry = gtk_entry_new(); gtk_container_add(GTK_CONTAINER(button), label); gtk_container_add(GTK_CONTAINER(combobox), comboboxLabel); @@ -756,6 +757,7 @@ nsLookAndFeel::InitLookAndFeel() gtk_container_add(GTK_CONTAINER(parent), combobox); gtk_container_add(GTK_CONTAINER(parent), menuBar); gtk_container_add(GTK_CONTAINER(window), parent); + gtk_container_add(GTK_CONTAINER(parent), entry); gtk_widget_set_style(button, NULL); gtk_widget_set_style(label, NULL); @@ -764,6 +766,7 @@ nsLookAndFeel::InitLookAndFeel() gtk_widget_set_style(combobox, NULL); gtk_widget_set_style(comboboxLabel, NULL); gtk_widget_set_style(menuBar, NULL); + gtk_widget_set_style(entry, NULL); gtk_widget_realize(button); gtk_widget_realize(label); @@ -772,6 +775,7 @@ nsLookAndFeel::InitLookAndFeel() gtk_widget_realize(combobox); gtk_widget_realize(comboboxLabel); gtk_widget_realize(menuBar); + gtk_widget_realize(entry); style = gtk_widget_get_style(label); if (style) { @@ -840,11 +844,7 @@ nsLookAndFeel::InitLookAndFeel() sNativeHyperLinkText = NS_RGB(0x00,0x00,0xEE); } - gtk_widget_destroy(window); - // invisible character styles - GtkWidget *entry = gtk_entry_new(); - g_object_ref_sink(entry); guint value; g_object_get (entry, "invisible-char", &value, NULL); sInvisibleCharacter = PRUnichar(value); @@ -854,8 +854,7 @@ nsLookAndFeel::InitLookAndFeel() "cursor-aspect-ratio", &sCaretRatio, NULL); - gtk_widget_destroy(entry); - g_object_unref(entry); + gtk_widget_destroy(window); } // virtual diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 1c5ea4b7e6fc..37c8c6fd1a7a 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -39,6 +39,7 @@ * ***** END LICENSE BLOCK ***** */ #ifdef MOZ_PLATFORM_MAEMO +// needed to include hildon parts in gtk.h #define MAEMO_CHANGES #endif @@ -62,6 +63,7 @@ #include #ifdef MOZ_X11 #include +#include #ifdef AIX #include @@ -89,6 +91,7 @@ #include "nsIObserverService.h" #include "nsIdleService.h" +#include "nsIPropertyBag2.h" #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" @@ -4258,6 +4261,25 @@ nsWindow::Create(nsIWidget *aParent, g_signal_connect_after(default_settings, "notify::gtk-font-name", G_CALLBACK(theme_changed_cb), this); + +#ifdef MOZ_PLATFORM_MAEMO + if (mWindowType == eWindowType_toplevel) { + GdkWindow *gdkwin = mShell->window; + + // Tell the Hildon desktop that we support being rotated + gulong portrait_set = 1; + GdkAtom support = gdk_atom_intern("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE); + gdk_property_change(gdkwin, support, gdk_x11_xatom_to_atom(XA_CARDINAL), + 32, GDK_PROP_MODE_REPLACE, + (const guchar *) &portrait_set, 1); + + // Tell maemo-status-volume daemon to ungrab keys + gulong volume_set = 1; + GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE); + gdk_property_change(gdkwin, keys, gdk_x11_xatom_to_atom(XA_INTEGER), + 32, GDK_PROP_MODE_REPLACE, (const guchar *) &volume_set, 1); + } +#endif } if (mContainer) { diff --git a/widget/src/windows/TaskbarPreviewButton.cpp b/widget/src/windows/TaskbarPreviewButton.cpp index d50a55b5146d..645d1348a735 100644 --- a/widget/src/windows/TaskbarPreviewButton.cpp +++ b/widget/src/windows/TaskbarPreviewButton.cpp @@ -150,7 +150,7 @@ TaskbarPreviewButton::SetImage(imgIContainer *img) { NS_IMETHODIMP TaskbarPreviewButton::GetVisible(PRBool *visible) { - *visible = (Button().dwFlags & THBF_HIDDEN) == THBF_HIDDEN; + *visible = (Button().dwFlags & THBF_HIDDEN) != THBF_HIDDEN; return NS_OK; } diff --git a/widget/tests/window_composition_text_querycontent.xul b/widget/tests/window_composition_text_querycontent.xul index 20378fcb042c..f909ffa142db 100644 --- a/widget/tests/window_composition_text_querycontent.xul +++ b/widget/tests/window_composition_text_querycontent.xul @@ -26,7 +26,8 @@

- +

Here is a text frame.
+

@@ -78,7 +79,7 @@ const nsIDOMWindowUtils = Components.interfaces.nsIDOMWindowUtils; const kIsWin = (navigator.platform.indexOf("Win") == 0); const kIsMac = (navigator.platform.indexOf("Mac") == 0); -function checkQueryContentResult(aResult, aMessage, aID) +function checkQueryContentResult(aResult, aMessage) { ok(aResult, aMessage + ": the result is null"); if (!aResult) { @@ -741,7 +742,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) for (var i = 0; i < kTestingOffset.length; i++) { var textRect = synthesizeQueryTextRect(kTestingOffset[i], 1); if (!checkQueryContentResult(textRect, - "runCharAtPointTest (" + aTargetName + "): textRect", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): textRect: i=" + i)) { continue; } @@ -753,7 +754,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt1 = synthesizeCharAtPoint(textRect.left + 1, textRect.top + 1); if (checkQueryContentResult(charAtPt1, - "runCharAtPointTest (" + aTargetName + "): charAtPt1", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt1: i=" + i)) { ok(!charAtPt1.notFound, "runCharAtPointTest (" + aTargetName + "): charAtPt1 isn't found: i=" + i); if (!charAtPt1.notFound) { @@ -768,7 +769,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt2 = synthesizeCharAtPoint(textRect.left + textRect.width - 2, textRect.top + textRect.height - 2); if (checkQueryContentResult(charAtPt2, - "runCharAtPointTest (" + aTargetName + "): charAtPt2", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt2: i=" + i)) { ok(!charAtPt2.notFound, "runCharAtPointTest (" + aTargetName + "): charAtPt2 isn't found: i=" + i); if (!charAtPt2.notFound) { @@ -783,7 +784,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt3 = synthesizeCharAtPoint(textRect.left - 2, textRect.top + 1); if (checkQueryContentResult(charAtPt3, - "runCharAtPointTest (" + aTargetName + "): charAtPt3", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt3: i=" + i)) { is(charAtPt3.notFound, kLeftSideOffset[i] == kNone, kLeftSideOffset[i] == kNone ? "runCharAtPointTest (" + aTargetName + "): charAtPt3 is found: i=" + i : @@ -798,7 +799,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt4 = synthesizeCharAtPoint(textRect.left + textRect.width + 1, textRect.top + textRect.height - 2); if (checkQueryContentResult(charAtPt4, - "runCharAtPointTest (" + aTargetName + "): charAtPt4", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt4: i=" + i)) { is(charAtPt4.notFound, kRightSideOffset[i] == kNone, kRightSideOffset[i] == kNone ? "runCharAtPointTest (" + aTargetName + "): charAtPt4 is found: i=" + i : @@ -811,6 +812,25 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) } } +function runCharAtPointAtOutsideTest() +{ + textarea.focus(); + textarea.value = "some text"; + var editorRect = synthesizeQueryEditorRect(); + if (!checkQueryContentResult(editorRect, + "runCharAtPointAtOutsideTest: editorRect")) { + return; + } + // Check on a text node which is at the outside of editor. + var charAtPt = synthesizeCharAtPoint(editorRect.left + 20, + editorRect.top - 10); + if (checkQueryContentResult(charAtPt, + "runCharAtPointAtOutsideTest: charAtPt")) { + ok(charAtPt.notFound, + "runCharAtPointAtOutsideTest: charAtPt is found on outside of editor"); + } +} + function runTestOnAnotherContext(aPanelOrFrame, aFocusedEditor, aTestName) { aFocusedEditor.value = ""; @@ -976,6 +996,7 @@ function runTest() { runCompositionTest(); runCharAtPointTest(textarea, "textarea in the document"); + runCharAtPointAtOutsideTest(); runFrameTest(); runPanelTest(); } diff --git a/xpcom/glue/Monitor.h b/xpcom/glue/Monitor.h index cd2d8d8aac00..6d6b3851cbaf 100644 --- a/xpcom/glue/Monitor.h +++ b/xpcom/glue/Monitor.h @@ -233,7 +233,7 @@ public: nsresult NotifyAll() { - return mMonitor->Notify(); + return mMonitor->NotifyAll(); } private: diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index fe0c719e62e9..69c5ed10b983 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -303,6 +303,38 @@ public: */ #define NS_INIT_ISUPPORTS() ((void)0) +/** + * Use this macro to declare and implement the AddRef & Release methods for a + * given non-XPCOM _class. + * + * The implementations here should match NS_IMPL_ADDREF/NS_IMPL_RELEASE, minus + * the nsrefcnt return-value and the NS_ASSERT_OWNINGTHREAD() call. + * + * @param _class The name of the class implementing the method + */ +#define NS_INLINE_DECL_REFCOUNTING(_class) \ +public: \ + void AddRef(void) { \ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ + ++mRefCnt; \ + NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ + } \ + void Release(void) { \ + NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ + --mRefCnt; \ + NS_LOG_RELEASE(this, mRefCnt, #_class); \ + if (mRefCnt == 0) { \ + mRefCnt = 1; /* stabilize */ \ + NS_DELETEXPCOM(this); \ + } \ + } \ +protected: \ + nsAutoRefCnt mRefCnt; \ + NS_DECL_OWNINGTHREAD \ +public: + /** * Use this macro to implement the AddRef method for a given _class * @param _class The name of the class implementing the method diff --git a/xpcom/glue/nsISupportsUtils.h b/xpcom/glue/nsISupportsUtils.h index e20aa5e3ece8..7bfb89494650 100644 --- a/xpcom/glue/nsISupportsUtils.h +++ b/xpcom/glue/nsISupportsUtils.h @@ -108,10 +108,12 @@ extern "C++" { // yet still denies you the ability to |AddRef()| an |nsCOMPtr|. template inline -nsrefcnt +void ns_if_addref( T expr ) { - return expr ? expr->AddRef() : 0; + if (expr) { + expr->AddRef(); + } } } /* extern "C++" */