(doc, from, to, options, type)
| 6170 | |
| 6171 | // Create a marker, wire it up to the right lines, and |
| 6172 | function markText(doc, from, to, options, type) { |
| 6173 | // Shared markers (across linked documents) are handled separately |
| 6174 | // (markTextShared will call out to this again, once per |
| 6175 | // document). |
| 6176 | if (options && options.shared) return markTextShared(doc, from, to, options, type); |
| 6177 | // Ensure we are in an operation. |
| 6178 | if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); |
| 6179 | |
| 6180 | var marker = new TextMarker(doc, type), diff = cmp(from, to); |
| 6181 | if (options) copyObj(options, marker, false); |
| 6182 | // Don't connect empty markers unless clearWhenEmpty is false |
| 6183 | if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) |
| 6184 | return marker; |
| 6185 | if (marker.replacedWith) { |
| 6186 | // Showing up as a widget implies collapsed (widget replaces text) |
| 6187 | marker.collapsed = true; |
| 6188 | marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget"); |
| 6189 | if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true"); |
| 6190 | if (options.insertLeft) marker.widgetNode.insertLeft = true; |
| 6191 | } |
| 6192 | if (marker.collapsed) { |
| 6193 | if (conflictingCollapsedRange(doc, from.line, from, to, marker) || |
| 6194 | from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) |
| 6195 | throw new Error("Inserting collapsed marker partially overlapping an existing one"); |
| 6196 | sawCollapsedSpans = true; |
| 6197 | } |
| 6198 | |
| 6199 | if (marker.addToHistory) |
| 6200 | addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); |
| 6201 | |
| 6202 | var curLine = from.line, cm = doc.cm, updateMaxLine; |
| 6203 | doc.iter(curLine, to.line + 1, function(line) { |
| 6204 | if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) |
| 6205 | updateMaxLine = true; |
| 6206 | if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); |
| 6207 | addMarkedSpan(line, new MarkedSpan(marker, |
| 6208 | curLine == from.line ? from.ch : null, |
| 6209 | curLine == to.line ? to.ch : null)); |
| 6210 | ++curLine; |
| 6211 | }); |
| 6212 | // lineIsHidden depends on the presence of the spans, so needs a second pass |
| 6213 | if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { |
| 6214 | if (lineIsHidden(doc, line)) updateLineHeight(line, 0); |
| 6215 | }); |
| 6216 | |
| 6217 | if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); |
| 6218 | |
| 6219 | if (marker.readOnly) { |
| 6220 | sawReadOnlySpans = true; |
| 6221 | if (doc.history.done.length || doc.history.undone.length) |
| 6222 | doc.clearHistory(); |
| 6223 | } |
| 6224 | if (marker.collapsed) { |
| 6225 | marker.id = ++nextMarkerId; |
| 6226 | marker.atomic = true; |
| 6227 | } |
| 6228 | if (cm) { |
| 6229 | // Sync editor state |
no test coverage detected