summaryrefslogtreecommitdiffstats
path: root/WebKit/gtk
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-01-05 12:15:11 +0000
committerSteve Block <steveblock@google.com>2011-01-06 14:14:00 +0000
commitd06194330da2bb8da887d2e1adeacb3a5c1504b2 (patch)
treee0af8413af65a8e30630563441af7bdb8478e513 /WebKit/gtk
parent419a5cf2f8db6ca014df624865197ffb82caad37 (diff)
downloadexternal_webkit-d06194330da2bb8da887d2e1adeacb3a5c1504b2.zip
external_webkit-d06194330da2bb8da887d2e1adeacb3a5c1504b2.tar.gz
external_webkit-d06194330da2bb8da887d2e1adeacb3a5c1504b2.tar.bz2
Merge WebKit at r72805: Initial merge by Git
Note that this is a backwards merge from Chromium release 9.0.600.0 to 9.0.597.0, to align with the Chromium 9 stable release branch. Change-Id: I5d2bb4e8cee9d39ae8485abf48bdb55ecf8b3790
Diffstat (limited to 'WebKit/gtk')
-rw-r--r--WebKit/gtk/ChangeLog76
-rw-r--r--WebKit/gtk/NEWS17
-rw-r--r--WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp9
-rw-r--r--WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp2
-rw-r--r--WebKit/gtk/WebCoreSupport/EditorClientGtk.h2
-rw-r--r--WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp32
-rw-r--r--WebKit/gtk/tests/testatk.c148
-rw-r--r--WebKit/gtk/webkit/webkitwebdatasource.cpp2
-rw-r--r--WebKit/gtk/webkit/webkitwebframe.cpp4
-rw-r--r--WebKit/gtk/webkit/webkitwebview.cpp6
10 files changed, 101 insertions, 197 deletions
diff --git a/WebKit/gtk/ChangeLog b/WebKit/gtk/ChangeLog
index d455df9..90aeaa4 100644
--- a/WebKit/gtk/ChangeLog
+++ b/WebKit/gtk/ChangeLog
@@ -1,79 +1,3 @@
-2010-12-01 Jia Pu <jpu@apple.com>
-
- Reviewed by Darin Adler.
-
- Support multiple correction candidates panel for misspelled word on Mac OS X.
- https://bugs.webkit.org/show_bug.cgi?id=50137
- <rdar://problem/8568059>
-
- Adopted new function signature defined in base class.
-
- * WebCoreSupport/EditorClientGtk.cpp:
- (WebKit::EditorClient::getGuessesForWord):
- * WebCoreSupport/EditorClientGtk.h:
-
-2010-11-30 Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
-
- Reviewed by Martin Robinson.
-
- [GTK] Fix wrong type in assert return value
- https://bugs.webkit.org/show_bug.cgi?id=50208
-
- Use appropriate return type in different g_return_val_if_fail(). This
- removes some compiler warning.
-
- * webkit/webkitwebdatasource.cpp:
- (webkit_web_data_source_is_loading):
- * webkit/webkitwebframe.cpp:
- (webkit_web_frame_page_number_for_element_by_id):
- (webkit_web_frame_number_of_pages):
-
-2010-11-30 Mario Sanchez Prada <msanchez@igalia.com>
-
- Reviewed by Chris Fleizach.
-
- [GTK] Implement ROLE_COMBO_BOX
- https://bugs.webkit.org/show_bug.cgi?id=25678
-
- New test to check the implementation of the combo boxes.
-
- * tests/testatk.c:
- (testWebkitAtkComboBox): New test, checking that the roles and the
- implemented interfaces for a combo box and its descendants work.
- (main): Added the new unit test.
-
-2010-11-30 Carlos Garcia Campos <cgarcia@igalia.com>
-
- Reviewed by Martin Robinson.
-
- [GTK] Test fast/events/mouseover-mouseout2.html crashes
- https://bugs.webkit.org/show_bug.cgi?id=50214
-
- * WebCoreSupport/ChromeClientGtk.cpp:
- (WebKit::ChromeClient::mouseDidMoveOverElement):
- * webkit/webkitwebview.cpp:
- (webkit_web_view_query_tooltip):
-
-2010-11-30 Sheriff Bot <webkit.review.bot@gmail.com>
-
- Unreviewed, rolling out r72764.
- http://trac.webkit.org/changeset/72764
- https://bugs.webkit.org/show_bug.cgi?id=50215
-
- This change is causing assertion failures on the debug bots.
- (Requested by mrobinson on #webkit).
-
- * WebCoreSupport/FrameLoaderClientGtk.cpp:
- (WebKit::notifyStatus):
- * tests/testatk.c:
- (main):
-
-2010-11-29 Xan Lopez <xlopez@igalia.com>
-
- Reviewed by Martin Robinson.
-
- * NEWS: update for 1.3.7 release.
-
2010-11-29 Carlos Garcia Campos <cgarcia@igalia.com>
Reviewed by Xan Lopez.
diff --git a/WebKit/gtk/NEWS b/WebKit/gtk/NEWS
index 03db88b..ead8923 100644
--- a/WebKit/gtk/NEWS
+++ b/WebKit/gtk/NEWS
@@ -1,21 +1,4 @@
================
-WebKitGTK+ 1.3.7
-================
-
-What's new in WebKitGTK+ 1.3.7?
-
- - Fix error pages template's not being filled properly.
- - Fix context menu activation through keyboard.
- - Add automatic garbage collection for most GObject DOM objects (all
- those that are actually in the DOM tree). This gets rid of most of
- the leaks when using the bindings.
- - Add an Inspector API to inspect a DOM node.
- - Tons of a11y bugfixes.
- - Tons of fixes for the in-tree SoupCache, should work much better
- now.
- - Many other bugfixes.
-
-================
WebKitGTK+ 1.3.6
================
diff --git a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
index 190ae9b..4450e87 100644
--- a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
+++ b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
@@ -523,12 +523,9 @@ void ChromeClient::mouseDidMoveOverElement(const HitTestResult& hit, unsigned mo
m_hoveredLinkURL = KURL();
}
- if (Node* node = hit.innerNonSharedNode()) {
- Frame* frame = node->document()->frame();
- FrameView* view = frame ? frame->view() : 0;
- m_webView->priv->tooltipArea = view ? view->contentsToWindow(node->getRect()) : IntRect();
- } else
- m_webView->priv->tooltipArea = IntRect();
+ Node* node = hit.innerNonSharedNode();
+
+ m_webView->priv->tooltipArea = node ? node->document()->frame()->view()->contentsToWindow(node->getRect()) : IntRect();
}
void ChromeClient::setToolTip(const String& toolTip, TextDirection)
diff --git a/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp b/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
index da07e56..bd88480 100644
--- a/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
+++ b/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
@@ -1008,7 +1008,7 @@ bool EditorClient::spellingUIIsShowing()
return false;
}
-void EditorClient::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses)
+void EditorClient::getGuessesForWord(const String& word, WTF::Vector<String>& guesses)
{
GSList* dicts = webkit_web_settings_get_enchant_dicts(m_webView);
guesses.clear();
diff --git a/WebKit/gtk/WebCoreSupport/EditorClientGtk.h b/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
index 22543c6..f9ff82e 100644
--- a/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
+++ b/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
@@ -129,7 +129,7 @@ namespace WebKit {
virtual void updateSpellingUIWithMisspelledWord(const WTF::String&);
virtual void showSpellingUI(bool show);
virtual bool spellingUIIsShowing();
- virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
+ virtual void getGuessesForWord(const WTF::String&, WTF::Vector<WTF::String>& guesses);
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool enabled);
diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
index fdef9dc..e7a2457 100644
--- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
+++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "FrameLoaderClientGtk.h"
+#include "AXObjectCache.h"
#include "ArchiveResource.h"
#include "CachedFrame.h"
#include "Color.h"
@@ -208,6 +209,34 @@ String FrameLoaderClient::userAgent(const KURL& url)
return String::fromUTF8(webkit_web_settings_get_user_agent(settings));
}
+static void notifyAccessibilityStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
+{
+ WebKitWebView* webView = getViewFromFrame(frame);
+ if (!webView || frame != webkit_web_view_get_main_frame(webView))
+ return;
+
+ AtkObject* axObject = gtk_widget_get_accessible(GTK_WIDGET(webView));
+ if (!axObject || !ATK_IS_DOCUMENT(axObject))
+ return;
+
+ switch (loadStatus) {
+ case WEBKIT_LOAD_PROVISIONAL:
+ g_signal_emit_by_name(axObject, "state-change", "busy", true);
+ if (core(frame)->loader()->loadType() == FrameLoadTypeReload)
+ g_signal_emit_by_name(axObject, "reload");
+ break;
+ case WEBKIT_LOAD_FAILED:
+ g_signal_emit_by_name(axObject, "load-stopped");
+ g_signal_emit_by_name(axObject, "state-change", "busy", false);
+ break;
+ case WEBKIT_LOAD_FINISHED:
+ g_signal_emit_by_name(axObject, "load-complete");
+ g_signal_emit_by_name(axObject, "state-change", "busy", false);
+ default:
+ break;
+ }
+}
+
static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
{
frame->priv->loadStatus = loadStatus;
@@ -218,6 +247,9 @@ static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
webView->priv->loadStatus = loadStatus;
g_object_notify(G_OBJECT(webView), "load-status");
}
+
+ if (AXObjectCache::accessibilityEnabled())
+ notifyAccessibilityStatus(frame, loadStatus);
}
static void loadDone(WebKitWebFrame* frame, bool didSucceed)
diff --git a/WebKit/gtk/tests/testatk.c b/WebKit/gtk/tests/testatk.c
index abd6091..94f4a96 100644
--- a/WebKit/gtk/tests/testatk.c
+++ b/WebKit/gtk/tests/testatk.c
@@ -21,6 +21,7 @@
#include <glib.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
+#include <stdlib.h>
#include <unistd.h>
#include <webkit/webkit.h>
@@ -44,8 +45,6 @@ static const char* contentsInTable = "<html><body><table><tr><td>foo</td><td>bar
static const char* contentsInTableWithHeaders = "<html><body><table><tr><th>foo</th><th>bar</th><th colspan='2'>baz</th></tr><tr><th>qux</th><td>1</td><td>2</td><td>3</td></tr><tr><th rowspan='2'>quux</th><td>4</td><td>5</td><td>6</td></tr><tr><td>6</td><td>7</td><td>8</td></tr><tr><th>corge</th><td>9</td><td>10</td><td>11</td></tr></table><table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></body></html>";
-static const char* comboBoxSelector = "<html><body><select><option selected value='foo'>foo</option><option value='bar'>bar</option></select></body></html>";
-
static const char* formWithTextInputs = "<html><body><form><input type='text' name='entry' /></form></body></html>";
static const char* hypertextAndHyperlinks = "<html><body><p>A paragraph with no links at all</p><p><a href='http://foo.bar.baz/'>A line</a> with <a href='http://bar.baz.foo/'>a link in the middle</a> as well as at the beginning and <a href='http://baz.foo.bar/'>at the end</a></p></body></html>";
@@ -223,107 +222,78 @@ static void runGetTextTests(AtkText* textObject)
0, "This is a test. This is the second sentence. And this the third.", 0, 64);
}
-static void testWebkitAtkComboBox()
+static void stateChangedCb(AtkObject* object, gchar* stateName, gboolean stateSet, gpointer unused)
+{
+ /* Only 'defunct' and 'busy' state changes are considered. */
+ if (!g_strcmp0(stateName, "defunct")) {
+ g_print("[defunct]");
+ return;
+ }
+
+ if (!g_strcmp0(stateName, "busy")) {
+ g_print("[busy:%d]", stateSet);
+ /* If 'busy' state is unset, it means we're done. */
+ if (!stateSet)
+ exit(0);
+ }
+}
+
+static void documentReloadCb(AtkDocument* document, gpointer unused)
+{
+ g_print("[reloaded]");
+}
+
+static void documentLoadCompleteCb(AtkDocument* document, gpointer unused)
+{
+ g_print("[load completed]");
+}
+
+static void webviewLoadStatusChangedCb(WebKitWebView* webView, GParamSpec* pspec, gpointer unused)
+{
+ /* We need to explicitly connect here to the signals emitted by
+ * the AtkObject associated to the webView because the AtkObject
+ * iniatially associated at the beginning of the process (when in
+ * the LOAD_PROVISIONAL state) will get destroyed and replaced by
+ * a new one later on, when the LOAD_COMMITED state is reached. */
+ WebKitLoadStatus loadStatus = webkit_web_view_get_load_status(webView);
+ if (loadStatus == WEBKIT_LOAD_PROVISIONAL || loadStatus == WEBKIT_LOAD_COMMITTED) {
+ AtkObject* axWebView = gtk_widget_get_accessible(GTK_WIDGET(webView));
+ g_assert(ATK_IS_DOCUMENT(axWebView));
+
+ g_signal_connect(axWebView, "state-change", G_CALLBACK(stateChangedCb), 0);
+ g_signal_connect(axWebView, "reload", G_CALLBACK(documentReloadCb), 0);
+ g_signal_connect(axWebView, "load-complete", G_CALLBACK(documentLoadCompleteCb), 0);
+ }
+}
+
+static void testWebkitAtkDocumentReloadEvents()
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
g_object_ref_sink(webView);
GtkAllocation allocation = { 0, 0, 800, 600 };
gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, comboBoxSelector, 0, 0, 0);
+
+ webkit_web_view_load_string(webView, contents, 0, 0, 0);
/* Wait for the accessible objects to be created. */
waitForAccessibleObjects();
- AtkObject* object = gtk_widget_get_accessible(GTK_WIDGET(webView));
- g_assert(object);
+ AtkObject* axWebView = gtk_widget_get_accessible(GTK_WIDGET(webView));
+ g_assert(ATK_IS_DOCUMENT(axWebView));
- AtkObject* formObject = atk_object_ref_accessible_child(object, 0);
- g_assert(formObject);
-
- AtkObject* comboBox = atk_object_ref_accessible_child(formObject, 0);
- g_assert(ATK_IS_OBJECT(comboBox));
-
- AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0);
- g_assert(ATK_IS_OBJECT(menuPopup));
-
- AtkObject* item1 = atk_object_ref_accessible_child(menuPopup, 0);
- g_assert(ATK_IS_OBJECT(item1));
-
- AtkObject* item2 = atk_object_ref_accessible_child(menuPopup, 1);
- g_assert(ATK_IS_OBJECT(item2));
-
- /* Check roles. */
- g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX);
- g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU);
- g_assert(atk_object_get_role(item1) == ATK_ROLE_MENU_ITEM);
- g_assert(atk_object_get_role(item2) == ATK_ROLE_MENU_ITEM);
-
- /* Check the implementation of the AtkSelection interface. */
- g_assert(ATK_IS_SELECTION(comboBox));
- AtkSelection* atkSelection = ATK_SELECTION(comboBox);
- g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
- g_assert(atk_selection_is_child_selected(atkSelection, 0));
- g_assert(!atk_selection_is_child_selected(atkSelection, 1));
- AtkObject* selectedItem = atk_selection_ref_selection(atkSelection, 0);
- g_assert(selectedItem == item1);
- g_object_unref(selectedItem);
-
- /* Check the implementations of the AtkAction interface. */
- g_assert(ATK_IS_ACTION(comboBox));
- AtkAction* atkAction = ATK_ACTION(comboBox);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(menuPopup));
- atkAction = ATK_ACTION(menuPopup);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(item1));
- atkAction = ATK_ACTION(item1);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(item2));
- atkAction = ATK_ACTION(item2);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- /* After selecting the second item, selection should have changed. */
- g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
- g_assert(!atk_selection_is_child_selected(atkSelection, 0));
- g_assert(atk_selection_is_child_selected(atkSelection, 1));
- selectedItem = atk_selection_ref_selection(atkSelection, 0);
- g_assert(selectedItem == item2);
- g_object_unref(selectedItem);
-
- /* Check the implementation of the AtkText interface. */
- g_assert(ATK_IS_TEXT(item1));
- AtkText* atkText = ATK_TEXT(item1);
- char *text = atk_text_get_text(atkText, 0, -1);
- g_assert_cmpstr(text, ==, "foo");
- g_free(text);
- text = atk_text_get_text(atkText, 0, 2);
- g_assert_cmpstr(text, ==, "fo");
- g_free(text);
+ if (g_test_trap_fork (2000000, G_TEST_TRAP_SILENCE_STDOUT)) {
+ g_signal_connect(webView, "notify::load-status", G_CALLBACK(webviewLoadStatusChangedCb), 0);
+ webkit_web_view_reload(webView);
+ }
- g_assert(ATK_IS_TEXT(item2));
- atkText = ATK_TEXT(item2);
- text = atk_text_get_text(atkText, 0, -1);
- g_assert_cmpstr(text, ==, "bar");
- g_free(text);
- text = atk_text_get_text(atkText, 1, 3);
- g_assert_cmpstr(text, ==, "ar");
- g_free(text);
+ /* Check results. */
+ g_test_trap_assert_passed();
+ g_test_trap_assert_stdout("[busy:1][reloaded][defunct][load completed][busy:0]");
- g_object_unref(formObject);
- g_object_unref(comboBox);
- g_object_unref(menuPopup);
- g_object_unref(item1);
- g_object_unref(item2);
g_object_unref(webView);
}
+
static void testWebkitAtkGetTextAtOffsetForms()
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
@@ -1314,7 +1284,7 @@ int main(int argc, char** argv)
gtk_test_init(&argc, &argv, 0);
g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/atk/comboBox", testWebkitAtkComboBox);
+ g_test_add_func("/webkit/atk/documentReloadEvents", testWebkitAtkDocumentReloadEvents);
g_test_add_func("/webkit/atk/getTextAtOffset", testWebkitAtkGetTextAtOffset);
g_test_add_func("/webkit/atk/getTextAtOffsetForms", testWebkitAtkGetTextAtOffsetForms);
g_test_add_func("/webkit/atk/getTextAtOffsetNewlines", testWebkitAtkGetTextAtOffsetNewlines);
diff --git a/WebKit/gtk/webkit/webkitwebdatasource.cpp b/WebKit/gtk/webkit/webkitwebdatasource.cpp
index 3673a99..38c9c48 100644
--- a/WebKit/gtk/webkit/webkitwebdatasource.cpp
+++ b/WebKit/gtk/webkit/webkitwebdatasource.cpp
@@ -318,7 +318,7 @@ G_CONST_RETURN gchar* webkit_web_data_source_get_encoding(WebKitWebDataSource* w
*/
gboolean webkit_web_data_source_is_loading(WebKitWebDataSource* webDataSource)
{
- g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), FALSE);
+ g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
diff --git a/WebKit/gtk/webkit/webkitwebframe.cpp b/WebKit/gtk/webkit/webkitwebframe.cpp
index 0e0c3c6..fcb5197 100644
--- a/WebKit/gtk/webkit/webkitwebframe.cpp
+++ b/WebKit/gtk/webkit/webkitwebframe.cpp
@@ -847,7 +847,7 @@ gchar* webkit_web_frame_counter_value_for_element_by_id(WebKitWebFrame* frame, c
*/
int webkit_web_frame_page_number_for_element_by_id(WebKitWebFrame* frame, const gchar* id, float pageWidth, float pageHeight)
{
- g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
+ g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
Frame* coreFrame = core(frame);
if (!coreFrame)
@@ -869,7 +869,7 @@ int webkit_web_frame_page_number_for_element_by_id(WebKitWebFrame* frame, const
*/
int webkit_web_frame_number_of_pages(WebKitWebFrame* frame, float pageWidth, float pageHeight)
{
- g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), 0);
+ g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL);
Frame* coreFrame = core(frame);
if (!coreFrame)
diff --git a/WebKit/gtk/webkit/webkitwebview.cpp b/WebKit/gtk/webkit/webkitwebview.cpp
index 90be935..3e888f8 100644
--- a/WebKit/gtk/webkit/webkitwebview.cpp
+++ b/WebKit/gtk/webkit/webkitwebview.cpp
@@ -1670,10 +1670,8 @@ static gboolean webkit_web_view_query_tooltip(GtkWidget *widget, gint x, gint y,
if (titleNode->isElementNode()) {
String title = static_cast<Element*>(titleNode)->title();
if (!title.isEmpty()) {
- if (FrameView* view = coreFrame->view()) {
- GdkRectangle area = view->contentsToWindow(node->getRect());
- gtk_tooltip_set_tip_area(tooltip, &area);
- }
+ GdkRectangle area = coreFrame->view()->contentsToWindow(node->getRect());
+ gtk_tooltip_set_tip_area(tooltip, &area);
gtk_tooltip_set_text(tooltip, title.utf8().data());
return TRUE;