Commit cf22dbac authored by bdakin@apple.com's avatar bdakin@apple.com
Browse files

WebCore:

2008-10-14  Maxime Britto  <britto@apple.com>

        Reviewed by Darin Adler, tweaked and landed by Beth.

        * WebCore.base.exp: Exposes two functions to be able to create a 
        selection from a point on the screen. Also exposes the new 
        TextIterator::currentNode function.
        * WebCore/editing/TextIterator.cpp:
        (TextIterator::currentNode) : New function that returns the current 
        text node or NULL if there is no text node.

WebKit:

2008-10-14  Maxime Britto  <britto@apple.com>

        Reviewed by Darin Adler.

        * WebKit.xcodeproj/project.pbxproj: Added two files for the 
        WebTextIterator, and made the WebTextIterator.h private

WebKit/mac:

2008-10-14  Maxime Britto  <britto@apple.com>

        Reviewed by Darin Adler.

        Added SPI to use WebCore's TextIterator with WebKit.

        * WebView/WebTextIterator.h: Added.
        * WebView/WebTextIterator.mm: Added.
        (-[WebTextIteratorPrivate dealloc]):
        (-[WebTextIterator dealloc]):
        (-[WebTextIterator initWithRange:]): Creates a TextIterator 
        instance
        (-[WebTextIterator advance]): Asks the iterator to advance() .
        (-[WebTextIterator currentNode]): Returns the current DOMNode from 
        the iterator
        (-[WebTextIterator currentText]): Returns the current text from the 
        iterator
        (-[WebTextIterator atEnd]): Indicated whether the iterator has 
        reached the end of the range.
        * WebView/WebView.h:
        * WebView/WebView.mm:
        (-[WebView textIteratorForRect:]): Returns a WebTextIterator with 
        the DOMRange contained in the rectangle given as a parameter.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@37611 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c6012911
2008-10-14 Maxime Britto <britto@apple.com>
Reviewed by Darin Adler, tweaked and landed by Beth.
* WebCore.base.exp: Exposes two functions to be able to create a
selection from a point on the screen. Also exposes the new
TextIterator::currentNode function.
* WebCore/editing/TextIterator.cpp:
(TextIterator::currentNode) : New function that returns the current
text node or NULL if there is no text node.
2008-10-15 Marco Barisione <marco.barisione@collabora.co.uk>
 
Reviewed by Holger Freyther.
......
......@@ -130,6 +130,8 @@ __ZN7WebCore10CachedPage25setCachedPagePlatformDataEPNS_22CachedPagePlatformData
__ZN7WebCore10EventNames10clickEventE
__ZN7WebCore10EventNames12keydownEventE
__ZN7WebCore10MouseEventC1ERKNS_12AtomicStringEbbN3WTF10PassRefPtrINS_9DOMWindowEEEiiiiibbbbtNS5_INS_15EventTargetNodeEEENS5_INS_9ClipboardEEEb
__ZN7WebCore10ScrollView17setScrollbarModesENS_13ScrollbarModeES1_
__ZN7WebCore10ScrollView20setCanHaveScrollbarsEb
__ZN7WebCore10StringImpl7replaceEtt
__ZN7WebCore10StringImplD1Ev
__ZN7WebCore10StringImplcvP8NSStringEv
......@@ -467,6 +469,7 @@ __ZN7WebCore5Frame16adjustPageHeightEPffff
__ZN7WebCore5Frame17setIsDisconnectedEb
__ZN7WebCore5Frame20setSelectionFromNoneEv
__ZN7WebCore5Frame21markAllMatchesForTextERKNS_6StringEbj
__ZN7WebCore5Frame23visiblePositionForPointERKNS_8IntPointE
__ZN7WebCore5Frame24computeAndSetTypingStyleEPNS_19CSSStyleDeclarationENS_10EditActionE
__ZN7WebCore5Frame24setExcludeFromTextSearchEb
__ZN7WebCore5Frame25matchLabelsAgainstElementEP7NSArrayPNS_7ElementE
......@@ -531,8 +534,8 @@ __ZN7WebCore6StringC1EP8NSString
__ZN7WebCore6StringC1EPKc
__ZN7WebCore6StringC1EPKcj
__ZN7WebCore6StringC1ERKN3JSC7UStringE
__ZN7WebCore6Widget16removeFromParentEv
__ZN7WebCore6Widget12setFrameRectERKNS_7IntRectE
__ZN7WebCore6Widget16removeFromParentEv
__ZN7WebCore6Widget20retainPlatformWidgetEv
__ZN7WebCore6Widget21releasePlatformWidgetEv
__ZN7WebCore6Widget4hideEv
......@@ -612,10 +615,10 @@ __ZN7WebCore9FrameView14setTransparentEb
__ZN7WebCore9FrameView15setMarginHeightEi
__ZN7WebCore9FrameView18updateControlTintsEv
__ZN7WebCore9FrameView22setBaseBackgroundColorENS_5ColorE
__ZN7WebCore9FrameView23layoutIfNeededRecursiveEv
__ZN7WebCore9FrameView29setShouldUpdateWhileOffscreenEb
__ZN7WebCore9FrameViewC1EPNS_5FrameE
__ZN7WebCore9HTMLNames8frameTagE
__ZN7WebCore9HTMLNames9iframeTagE
__ZN7WebCore9FrameViewC1EPNS_5FrameERKNS_7IntSizeE
__ZN7WebCore9HTMLNames10listingTagE
__ZN7WebCore9HTMLNames13blockquoteTagE
__ZN7WebCore9HTMLNames4aTagE
......@@ -643,8 +646,10 @@ __ZN7WebCore9HTMLNames6imgTagE
__ZN7WebCore9HTMLNames6preTagE
__ZN7WebCore9HTMLNames7formTagE
__ZN7WebCore9HTMLNames7srcAttrE
__ZN7WebCore9HTMLNames8frameTagE
__ZN7WebCore9HTMLNames8hrefAttrE
__ZN7WebCore9HTMLNames8inputTagE
__ZN7WebCore9HTMLNames9iframeTagE
__ZN7WebCore9PageCache11setCapacityEi
__ZN7WebCore9PageCache27releaseAutoreleasedPagesNowEv
__ZN7WebCore9PageGroup14addVisitedLinkEPKtm
......@@ -653,6 +658,7 @@ __ZN7WebCore9PageGroup21removeAllVisitedLinksEv
__ZN7WebCore9PageGroup26setShouldTrackVisitedLinksEb
__ZN7WebCore9Selection22expandUsingGranularityENS_15TextGranularityE
__ZN7WebCore9SelectionC1EPKNS_5RangeENS_9EAffinityE
__ZN7WebCore9SelectionC1ERKNS_15VisiblePositionES3_
__ZN7WebCore9TimerBase4stopEv
__ZN7WebCore9TimerBase5startEdd
__ZN7WebCore9TimerBaseC2Ev
......@@ -664,8 +670,6 @@ __ZN7WebCoreplERKNS_6StringES2_
__ZNK3JSC8Bindings10RootObject12globalObjectEv
__ZNK7WebCore10PluginData16supportsMimeTypeERKNS_6StringE
__ZNK7WebCore10ScrollView12documentViewEv
__ZN7WebCore10ScrollView17setScrollbarModesENS_13ScrollbarModeES1_
__ZN7WebCore10ScrollView20setCanHaveScrollbarsEb
__ZNK7WebCore10ScrollView14scrollbarModesERNS_13ScrollbarModeES2_
__ZNK7WebCore11CachedImage5imageEv
__ZNK7WebCore11ContextMenu19platformDescriptionEv
......@@ -710,7 +714,10 @@ __ZNK7WebCore12RenderObject25backslashAsCurrencySymbolEv
__ZNK7WebCore12SharedBuffer4dataEv
__ZNK7WebCore12SharedBuffer4sizeEv
__ZNK7WebCore12TextEncoding6decodeEPKcmbRb
__ZNK7WebCore12TextIterator4nodeEv
__ZNK7WebCore12TextIterator5rangeEv
__ZNK7WebCore13ContainerNode14childNodeCountEv
__ZNK7WebCore13ContainerNode9childNodeEj
__ZNK7WebCore13HitTestResult10isLiveLinkEv
__ZNK7WebCore13HitTestResult10isSelectedEv
__ZNK7WebCore13HitTestResult11targetFrameEv
......@@ -725,7 +732,6 @@ __ZNK7WebCore13HitTestResult5imageEv
__ZNK7WebCore13HitTestResult5titleEv
__ZNK7WebCore13HitTestResult9imageRectEv
__ZNK7WebCore13ResourceErrorcvP7NSErrorEv
__ZNK7WebCore13ContainerNode14childNodeCountEv
__ZNK7WebCore14DocumentLoader10requestURLEv
__ZNK7WebCore14DocumentLoader11frameLoaderEv
__ZNK7WebCore14DocumentLoader11subresourceERKNS_4KURLE
......@@ -772,7 +778,6 @@ __ZNK7WebCore4KURLcvP5NSURLEv
__ZNK7WebCore4Node14isDescendantOfEPKS0_
__ZNK7WebCore4Node18getSubresourceURLsERN3WTF6VectorINS_4KURLELm0EEE
__ZNK7WebCore4Node9nodeIndexEv
__ZNK7WebCore13ContainerNode9childNodeEj
__ZNK7WebCore4Page10pluginDataEv
__ZNK7WebCore4Page34inLowQualityImageInterpolationModeEv
__ZNK7WebCore4Page9groupNameEv
......@@ -860,8 +865,6 @@ __ZNK7WebCore9FrameTree4findERKNS_12AtomicStringE
__ZNK7WebCore9FrameTree5childERKNS_12AtomicStringE
__ZNK7WebCore9FrameTree6parentEb
__ZNK7WebCore9FrameView11needsLayoutEv
__ZN7WebCore9FrameView23layoutIfNeededRecursiveEv
__ZN7WebCore9FrameViewC1EPNS_5FrameERKNS_7IntSizeE
__ZNK7WebCore9Selection17isContentEditableEv
__ZNK7WebCore9Selection19rootEditableElementEv
__ZNK7WebCore9Selection23isContentRichlyEditableEv
......
......@@ -712,6 +712,21 @@ PassRefPtr<Range> TextIterator::range() const
return 0;
}
Node* TextIterator::node() const
{
RefPtr<Range> textRange = range();
if (!textRange)
return 0;
Node* node = textRange->startContainer();
if (!node)
return 0;
if (node->offsetInCharacters())
return node;
return node->childNode(textRange->startOffset());
}
// --------
......
......@@ -65,6 +65,7 @@ public:
const UChar* characters() const { return m_textCharacters; }
PassRefPtr<Range> range() const;
Node* node() const;
static int rangeLength(const Range*, bool spacesForReplacedElements = false);
static PassRefPtr<Range> rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, bool spacesForReplacedElements = false);
......
2008-10-14 Maxime Britto <britto@apple.com>
Reviewed by Darin Adler.
* WebKit.xcodeproj/project.pbxproj: Added two files for the
WebTextIterator, and made the WebTextIterator.h private
2008-10-04 Mark Rowe <mrowe@apple.com>
Reviewed by Tim Hatcher.
......
......@@ -294,6 +294,8 @@
ED7F6D8B0980683500C235ED /* WebNSDataExtrasPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = ED7F6D8A0980683500C235ED /* WebNSDataExtrasPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
EDE983800BCDF5FE00FDAE28 /* WebNSArrayExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE9837E0BCDF5FE00FDAE28 /* WebNSArrayExtras.h */; };
EDE983810BCDF5FE00FDAE28 /* WebNSArrayExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = EDE9837F0BCDF5FE00FDAE28 /* WebNSArrayExtras.m */; };
F834AAD70E64B1C700E2737C /* WebTextIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = F834AAD50E64B1C700E2737C /* WebTextIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
F834AAD80E64B1C700E2737C /* WebTextIterator.mm in Sources */ = {isa = PBXBuildFile; fileRef = F834AAD60E64B1C700E2737C /* WebTextIterator.mm */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
......@@ -590,6 +592,8 @@
F7EBEE9B03F9DBA103CA0DE6 /* HIViewAdapter.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = HIViewAdapter.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
F7EBEEAA03F9DBA103CA0DE6 /* HIWebView.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HIWebView.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
F7EBEEAB03F9DBA103CA0DE6 /* HIWebView.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = HIWebView.m; sourceTree = "<group>"; usesTabs = 0; };
F834AAD50E64B1C700E2737C /* WebTextIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebTextIterator.h; sourceTree = "<group>"; };
F834AAD60E64B1C700E2737C /* WebTextIterator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebTextIterator.mm; sourceTree = "<group>"; };
F8CA15B5029A39D901000122 /* WebAuthenticationPanel.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebAuthenticationPanel.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
F8CA15B6029A39D901000122 /* WebAuthenticationPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebAuthenticationPanel.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
/* End PBXFileReference section */
......@@ -919,6 +923,8 @@
9C7CABBB0190A37C0ECA16EA /* WebView */ = {
isa = PBXGroup;
children = (
F834AAD50E64B1C700E2737C /* WebTextIterator.h */,
F834AAD60E64B1C700E2737C /* WebTextIterator.mm */,
F52CA6BD02DF9D0F018635CA /* HTML */,
51E94C0706C02CA300A9B09E /* PDF */,
8373435A0624EE0D00F3B289 /* WebArchive.h */,
......@@ -1303,6 +1309,7 @@
1A2D754D0DE480B900F0A648 /* WebIconFetcher.h in Headers */,
1A2D75500DE4810E00F0A648 /* WebIconFetcherInternal.h in Headers */,
5D1638F30E35B45D00F3038E /* EmptyProtocolDefinitions.h in Headers */,
F834AAD70E64B1C700E2737C /* WebTextIterator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -1585,6 +1592,7 @@
1AEA66D90DC6B209003D12BF /* WebNetscapePluginEventHandlerCarbon.mm in Sources */,
1AEA6A510DC8CE2F003D12BF /* WebNetscapePluginEventHandlerCocoa.mm in Sources */,
1A2D754E0DE480B900F0A648 /* WebIconFetcher.mm in Sources */,
F834AAD80E64B1C700E2737C /* WebTextIterator.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
2008-10-14 Maxime Britto <britto@apple.com>
Reviewed by Darin Adler.
Added SPI to use WebCore's TextIterator with WebKit.
* WebView/WebTextIterator.h: Added.
* WebView/WebTextIterator.mm: Added.
(-[WebTextIteratorPrivate dealloc]):
(-[WebTextIterator dealloc]):
(-[WebTextIterator initWithRange:]): Creates a TextIterator
instance
(-[WebTextIterator advance]): Asks the iterator to advance() .
(-[WebTextIterator currentNode]): Returns the current DOMNode from
the iterator
(-[WebTextIterator currentText]): Returns the current text from the
iterator
(-[WebTextIterator atEnd]): Indicated whether the iterator has
reached the end of the range.
* WebView/WebView.h:
* WebView/WebView.mm:
(-[WebView textIteratorForRect:]): Returns a WebTextIterator with
the DOMRange contained in the rectangle given as a parameter.
2008-10-15 Timothy Hatcher <timothy@apple.com>
Clean up user agent generation to simplify the _standardUserAgentWithApplicationName:
......
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/Foundation.h>
@class DOMRange;
@class DOMNode;
@class WebTextIteratorPrivate;
@interface WebTextIterator : NSObject
{
@private
WebTextIteratorPrivate *_private;
}
- (id)initWithRange:(DOMRange *)range;
/*!
@method advance:
@abstract Makes the WebTextIterator iterate to the next visible text element.
*/
- (void)advance;
/*!
@method currentNode:
@result The current DOMNode in the WebTextIterator.
*/
- (DOMNode *)currentNode;
/*!
@method currentText:
@result The current text in the WebTextIterator.
*/
- (NSString *)currentText;
/*!
@method atEnd:
@result YES if the WebTextIterator has reached the end of the DOMRange.
*/
- (BOOL)atEnd;
@end
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "WebTextIterator.h"
#import "DOMNodeInternal.h"
#import "DOMRangeInternal.h"
#import <WebCore/TextIterator.h>
#import <wtf/Vector.h>
using namespace WebCore;
@interface WebTextIteratorPrivate : NSObject
{
@public
TextIterator* m_textIterator;
}
@end
@implementation WebTextIteratorPrivate
- (void)dealloc
{
delete m_textIterator;
[super dealloc];
}
- (void)finalize
{
delete m_textIterator;
[super finalize];
}
@end
@implementation WebTextIterator
- (void)dealloc
{
[_private release];
[super dealloc];
}
- (id)initWithRange:(DOMRange *)range
{
self = [super init];
if (!self)
return self;
_private = [[WebTextIteratorPrivate alloc] init];
_private->m_textIterator = new TextIterator([range _range], true, false);
return self;
}
- (void)advance
{
ASSERT(_private->m_textIterator);
if (_private->m_textIterator->atEnd())
return;
_private->m_textIterator->advance();
}
- (DOMNode *)currentNode
{
ASSERT(_private->m_textIterator);
return [DOMNode _wrapNode:_private->m_textIterator->node()];
}
- (NSString *)currentText
{
ASSERT(_private->m_textIterator);
return [NSString stringWithCharacters:_private->m_textIterator->characters() length:_private->m_textIterator->length()];
}
- (BOOL)atEnd
{
ASSERT(_private->m_textIterator);
return _private->m_textIterator->atEnd();
}
@end
......@@ -84,6 +84,7 @@
#import "WebPolicyDelegate.h"
#import "WebPreferenceKeysPrivate.h"
#import "WebPreferencesPrivate.h"
#import "WebTextIterator.h"
#import "WebUIDelegate.h"
#import "WebUIDelegatePrivate.h"
#import <CoreFoundation/CFSet.h>
......@@ -1934,6 +1935,20 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati
[[self preferences] _postPreferencesChangesNotification];
}
- (WebTextIterator *)textIteratorForRect:(NSRect)rect
{
IntPoint rectStart(rect.origin.x, rect.origin.y);
IntPoint rectEnd(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
Frame* coreFrame = core([self mainFrame]);
if (!coreFrame)
return nil;
Selection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd));
return [[[WebTextIterator alloc] initWithRange:[DOMRange _wrapRange:selectionInsideRect.toRange().get()]] autorelease];
}
- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource
{
NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window];
......
......@@ -45,6 +45,7 @@
@class WebFrame;
@class WebInspector;
@class WebPreferences;
@class WebTextIterator;
@protocol WebFormDelegate;
......@@ -361,6 +362,13 @@ Could be worth adding to the API.
- (BOOL)usesPageCache;
- (void)setUsesPageCache:(BOOL)usesPageCache;
/*!
@method textIteratorForRect:
@param rectangle from which we want the WebTextIterator to load text from
@result a WebtextIterator object.
*/
- (WebTextIterator *)textIteratorForRect:(NSRect)rect;
#if ENABLE_DASHBOARD_SUPPORT
// <rdar://problem/5217124> Clients other than dashboard, don't use this.
// Do not remove until Dashboard has moved off it
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment