| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2011, Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y | |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y | |
| 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N | |
| 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 23 */ | |
| 24 | |
| 25 #include "config.h" | |
| 26 #include "core/inspector/InspectorStyleTextEditor.h" | |
| 27 | |
| 28 #include "core/css/CSSPropertySourceData.h" | |
| 29 #include "core/html/parser/HTMLParserIdioms.h" | |
| 30 #include "core/inspector/InspectorStyleSheet.h" | |
| 31 | |
| 32 namespace blink { | |
| 33 | |
| 34 InspectorStyleTextEditor::InspectorStyleTextEditor(WillBeHeapVector<InspectorSty
leProperty>* allProperties, const String& styleText, const SourceRange& styleRan
ge, const NewLineAndWhitespace& format) | |
| 35 : m_allProperties(allProperties) | |
| 36 , m_styleText(styleText) | |
| 37 , m_styleRange(styleRange) | |
| 38 , m_format(format) | |
| 39 { | |
| 40 } | |
| 41 | |
| 42 void InspectorStyleTextEditor::insertProperty(unsigned index, const String& prop
ertyText) | |
| 43 { | |
| 44 unsigned styleBodyLength = m_styleRange.length(); | |
| 45 long propertyStart = 0; | |
| 46 | |
| 47 bool insertLast = true; | |
| 48 if (index < m_allProperties->size()) { | |
| 49 const InspectorStyleProperty& property = m_allProperties->at(index); | |
| 50 if (property.hasSource) { | |
| 51 propertyStart = property.sourceData.range.start - m_styleRange.start
; | |
| 52 // If inserting before a disabled property, it should be shifted, to
o. | |
| 53 insertLast = false; | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 bool insertFirstInSource = !m_allProperties->size() || !m_allProperties->at(
0).hasSource; | |
| 58 bool insertLastInSource = true; | |
| 59 for (unsigned i = index, size = m_allProperties->size(); i < size; ++i) { | |
| 60 const InspectorStyleProperty& property = m_allProperties->at(i); | |
| 61 if (property.hasSource) { | |
| 62 insertLastInSource = false; | |
| 63 break; | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 String textToSet = propertyText; | |
| 68 | |
| 69 int formattingPrependOffset = 0; | |
| 70 if (insertLast && !insertFirstInSource) { | |
| 71 propertyStart = styleBodyLength; | |
| 72 if (propertyStart && textToSet.length()) { | |
| 73 long curPos = propertyStart - 1; // The last position of style decla
ration, since propertyStart points past one. | |
| 74 while (curPos && isHTMLSpace<UChar>(m_styleText[curPos])) | |
| 75 --curPos; | |
| 76 if (curPos) { | |
| 77 bool terminated = m_styleText[curPos] == ';' || (m_styleText[cur
Pos] == '/' && m_styleText[curPos - 1] == '*'); | |
| 78 if (!terminated) { | |
| 79 // Prepend a ";" to the property text if appending to a styl
e declaration where | |
| 80 // the last property has no trailing ";". | |
| 81 textToSet.insert(";", 0); | |
| 82 formattingPrependOffset = 1; | |
| 83 } | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 const String& formatLineFeed = m_format.first; | |
| 89 const String& formatPropertyPrefix = m_format.second; | |
| 90 if (insertLastInSource) { | |
| 91 long formatPropertyPrefixLength = formatPropertyPrefix.length(); | |
| 92 if (!formattingPrependOffset && (propertyStart < formatPropertyPrefixLen
gth || m_styleText.substring(propertyStart - formatPropertyPrefixLength, formatP
ropertyPrefixLength) != formatPropertyPrefix)) { | |
| 93 textToSet.insert(formatPropertyPrefix, formattingPrependOffset); | |
| 94 if (!propertyStart || !isHTMLLineBreak(m_styleText[propertyStart - 1
])) | |
| 95 textToSet.insert(formatLineFeed, formattingPrependOffset); | |
| 96 } | |
| 97 if (!isHTMLLineBreak(m_styleText[propertyStart])) | |
| 98 textToSet = textToSet + formatLineFeed; | |
| 99 } else { | |
| 100 String fullPrefix = formatLineFeed + formatPropertyPrefix; | |
| 101 long fullPrefixLength = fullPrefix.length(); | |
| 102 textToSet = textToSet + fullPrefix; | |
| 103 if (insertFirstInSource && (propertyStart < fullPrefixLength || m_styleT
ext.substring(propertyStart - fullPrefixLength, fullPrefixLength) != fullPrefix)
) | |
| 104 textToSet.insert(fullPrefix, formattingPrependOffset); | |
| 105 } | |
| 106 m_styleText.insert(textToSet, propertyStart); | |
| 107 } | |
| 108 | |
| 109 void InspectorStyleTextEditor::replaceProperty(unsigned index, const String& new
Text) | |
| 110 { | |
| 111 ASSERT_WITH_SECURITY_IMPLICATION(index < m_allProperties->size()); | |
| 112 internalReplaceProperty(m_allProperties->at(index), newText); | |
| 113 } | |
| 114 | |
| 115 void InspectorStyleTextEditor::internalReplaceProperty(const InspectorStylePrope
rty& property, const String& newText) | |
| 116 { | |
| 117 const SourceRange& range = property.sourceData.range; | |
| 118 long replaceRangeStart = range.start - m_styleRange.start; | |
| 119 long replaceRangeEnd = range.end - m_styleRange.start; | |
| 120 long newTextLength = newText.length(); | |
| 121 String finalNewText = newText; | |
| 122 | |
| 123 // Removing a property - remove preceding prefix. | |
| 124 String fullPrefix = m_format.first + m_format.second; | |
| 125 long fullPrefixLength = fullPrefix.length(); | |
| 126 if (!newTextLength && fullPrefixLength) { | |
| 127 if (replaceRangeStart >= fullPrefixLength && m_styleText.substring(repla
ceRangeStart - fullPrefixLength, fullPrefixLength) == fullPrefix) | |
| 128 replaceRangeStart -= fullPrefixLength; | |
| 129 } else if (newTextLength) { | |
| 130 if (isHTMLLineBreak(newText[newTextLength - 1])) { | |
| 131 // Coalesce newlines of the original and new property values (to avo
id a lot of blank lines while incrementally applying property values). | |
| 132 bool foundNewline = false; | |
| 133 bool isLastNewline = false; | |
| 134 int i; | |
| 135 int textLength = m_styleText.length(); | |
| 136 for (i = replaceRangeEnd; i < textLength && isSpaceOrNewline(m_style
Text[i]); ++i) { | |
| 137 isLastNewline = isHTMLLineBreak(m_styleText[i]); | |
| 138 if (isLastNewline) | |
| 139 foundNewline = true; | |
| 140 else if (foundNewline && !isLastNewline) { | |
| 141 replaceRangeEnd = i; | |
| 142 break; | |
| 143 } | |
| 144 } | |
| 145 if (foundNewline && isLastNewline) | |
| 146 replaceRangeEnd = i; | |
| 147 } | |
| 148 | |
| 149 if (fullPrefixLength > replaceRangeStart || m_styleText.substring(replac
eRangeStart - fullPrefixLength, fullPrefixLength) != fullPrefix) | |
| 150 finalNewText.insert(fullPrefix, 0); | |
| 151 } | |
| 152 | |
| 153 int replacedLength = replaceRangeEnd - replaceRangeStart; | |
| 154 m_styleText.replace(replaceRangeStart, replacedLength, finalNewText); | |
| 155 } | |
| 156 | |
| 157 } // namespace blink | |
| 158 | |
| OLD | NEW |