121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch// found in the LICENSE file.
421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch"use strict";
621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdochclass TextView extends View {
821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  constructor(id, broker, patterns, allowSpanSelection) {
921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    super(id, broker);
1021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
1121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.sortedPositionList = [];
1221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.nodePositionMap = [];
1321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.positionNodeMap = [];
1421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.textListNode = view.divNode.getElementsByTagName('ul')[0];
1521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.fillerSvgElement = view.divElement.append("svg").attr('version','1.1').attr("width", "0");
1621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.patterns = patterns;
1721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.allowSpanSelection = allowSpanSelection;
1821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.nodeToLineMap = [];
1921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    var selectionHandler = {
2021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      clear: function() {
2121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        broker.clear(selectionHandler);
2221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      },
2321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      select: function(items, selected) {
2421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        for (let i of items) {
2521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          if (selected) {
2621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            i.classList.add("selected");
2721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          } else {
2821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            i.classList.remove("selected");
2921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          }
3021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
3121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        broker.select(selectionHandler, view.getRanges(items), selected);
3221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      },
3321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      selectionDifference: function(span1, inclusive1, span2, inclusive2) {
3421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return null;
3521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      },
3621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      brokeredSelect: function(ranges, selected) {
3721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let locations = view.rangesToLocations(ranges);
3821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.selectLocations(locations, selected, true);
3921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      },
4021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      brokeredClear: function() {
4121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.selection.clear();
4221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
4321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    };
4421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.selection = new Selection(selectionHandler);
4521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    broker.addSelectionHandler(selectionHandler);
4621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
4721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
4821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  setPatterns(patterns) {
4921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
5021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.patterns = patterns;
5121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
5221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
5321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  clearText() {
5421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
5521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    while (view.textListNode.firstChild) {
5621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.textListNode.removeChild(view.textListNode.firstChild);
5721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
5821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
5921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
6021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  rangeToLocation(range) {
6121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return range;
6221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
6321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
6421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  rangesToLocations(ranges) {
6521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
6621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let nodes = new Set();
6721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let result = [];
6821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    for (let range of ranges) {
6921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let start = range[0];
7021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let end = range[1];
7121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let location = { pos_start: start, pos_end: end };
7221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (range[2] !== null && range[2] != -1) {
7321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        location.node_id = range[2];
7421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (range[0] == -1 && range[1] == -1) {
7521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          location.pos_start = view.nodePositionMap[location.node_id];
7621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          location.pos_end = location.pos_start + 1;
7721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
7821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      } else {
7921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (range[0] != undefined) {
8021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          location.pos_start = range[0];
8121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          location.pos_end = range[1];
8221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
8321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
8421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      result.push(location);
8521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
8621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return result;
8721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
8821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
8921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  sameLocation(l1, l2) {
9021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
9121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (l1.block_id != undefined && l2.block_id != undefined &&
9221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      l1.block_id == l2.block_id && l1.node_id === undefined) {
9321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return true;
9421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
9521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
9621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (l1.address != undefined && l1.address == l2.address) {
9721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return true;
9821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
9921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
10021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let node1 = l1.node_id;
10121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let node2 = l2.node_id;
10221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
10321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (node1 === undefined && node2 == undefined) {
10421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (l1.pos_start === undefined || l2.pos_start == undefined) {
10521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return false;
10621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
10721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (l1.pos_start == -1 || l2.pos_start == -1) {
10821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return false;
10921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
11021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (l1.pos_start < l2.pos_start) {
11121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return l1.pos_end > l2.pos_start;
11221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      } {
11321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return l1.pos_start < l2.pos_end;
11421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
11521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
11621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
11721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (node1 === undefined) {
11821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let lower = lowerBound(view.positionNodeMap, l1.pos_start, undefined, function(a, b) {
11921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        var node = a[b];
12021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return view.nodePositionMap[node];
12121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      } );
12221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      while (++lower < view.positionNodeMap.length &&
12321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch             view.nodePositionMap[view.positionNodeMap[lower]] < l1.pos_end) {
12421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (view.positionNodeMap[lower] == node2) {
12521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          return true;
12621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
12721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
12821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return false;
12921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
13021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
13121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (node2 === undefined) {
13221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let lower = lowerBound(view.positionNodeMap, l2.pos_start, undefined, function(a, b) {
13321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        var node = a[b];
13421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return view.nodePositionMap[node];
13521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      } );
13621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      while (++lower < view.positionNodeMap.length &&
13721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch             view.nodePositionMap[view.positionNodeMap[lower]] < l2.pos_end) {
13821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (view.positionNodeMap[lower] == node1) {
13921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          return true;
14021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
14121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
14221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return false;
14321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
14421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
14521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return l1.node_id == l2.node_id;
14621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
14721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
14821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  setNodePositionMap(map) {
14921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
15021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.nodePositionMap = map;
15121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.positionNodeMap = [];
15221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.sortedPositionList = [];
15321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let next = 0;
15421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    for (let i in view.nodePositionMap) {
15521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.sortedPositionList[next] = Number(view.nodePositionMap[i]);
15621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.positionNodeMap[next++] = i;
15721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
15821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.sortedPositionList = sortUnique(view.sortedPositionList,
15921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                         function(a,b) { return a - b; });
16021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    this.positionNodeMap.sort(function(a,b) {
16121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let result = view.nodePositionMap[a] - view.nodePositionMap[b];
16221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (result != 0) return result;
16321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return a - b;
16421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    });
16521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
16621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
16721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  selectLocations(locations, selected, makeVisible) {
16821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
16921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    for (let l of locations) {
17021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      for (let i = 0; i < view.textListNode.children.length; ++i) {
17121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let child = view.textListNode.children[i];
17221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (child.location != undefined && view.sameLocation(l, child.location)) {
17321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          view.selectCommon(child, selected, makeVisible);
17421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
17521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
17621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
17721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
17821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
17921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  getRanges(items) {
18021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let result = [];
18121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let lastObject = null;
18221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    for (let i of items) {
18321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (i.location) {
18421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let location = i.location;
18521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let start = -1;
18621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let end = -1;
18721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let node_id = -1;
18821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (location.node_id !== undefined) {
18921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          node_id = location.node_id;
19021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
19121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (location.pos_start !== undefined) {
19221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          start = location.pos_start;
19321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          end = location.pos_end;
19421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        } else {
19521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          if (this.nodePositionMap && this.nodePositionMap[node_id]) {
19621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            start = this.nodePositionMap[node_id];
19721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            end = start + 1;
19821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          }
19921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
20021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (lastObject == null ||
20121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            (lastObject[2] != node_id ||
20221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch             lastObject[0] != start ||
20321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch             lastObject[1] != end)) {
20421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          lastObject = [start, end, node_id];
20521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          result.push(lastObject);
20621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
20721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
20821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
20921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return result;
21021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
21121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
21221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  createFragment(text, style) {
21321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
21421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let span = document.createElement("SPAN");
21521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    span.onmousedown = function(e) {
21621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.mouseDownSpan(span, e);
21721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
21821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (style != undefined) {
21921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      span.classList.add(style);
22021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
22121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    span.innerText = text;
22221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return span;
22321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
22421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
22521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  appendFragment(li, fragment) {
22621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    li.appendChild(fragment);
22721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
22821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
22921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  processLine(line) {
23021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
23121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let result = [];
23221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let patternSet = 0;
23321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    while (true) {
23421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let beforeLine = line;
23521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      for (let pattern of view.patterns[patternSet]) {
23621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let matches = line.match(pattern[0]);
23721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (matches != null) {
23821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          if (matches[0] != '') {
23921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            let style = pattern[1] != null ? pattern[1] : {};
24021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            let text = matches[0];
24121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            if (text != '') {
24221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              let fragment = view.createFragment(matches[0], style.css);
24321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              if (style.link) {
24421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                fragment.classList.add('linkable-text');
24521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                fragment.link = style.link;
24621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              }
24721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              result.push(fragment);
24821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              if (style.location != undefined) {
24921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                let location = style.location(text);
25021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                if (location != undefined) {
25121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                  fragment.location = location;
25221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                }
25321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              }
25421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            }
25521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            line = line.substr(matches[0].length);
25621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          }
25721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          let nextPatternSet = patternSet;
25821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          if (pattern.length > 2) {
25921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            nextPatternSet = pattern[2];
26021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          }
26121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          if (line == "") {
26221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            if (nextPatternSet != -1) {
26321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              throw("illegal parsing state in text-view in patternSet" + patternSet);
26421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            }
26521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            return result;
26621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          }
26721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          patternSet = nextPatternSet;
26821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          break;
26921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
27021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
27121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (beforeLine == line) {
27221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        throw("input not consumed in text-view in patternSet" + patternSet);
27321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
27421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
27521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
27621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
27721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  select(s, selected, makeVisible) {
27821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
27921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.selection.clear();
28021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.selectCommon(s, selected, makeVisible);
28121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
28221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
28321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  selectCommon(s, selected, makeVisible) {
28421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
28521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let firstSelect = makeVisible && view.selection.isEmpty();
28621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if ((typeof s) === 'function') {
28721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      for (let i = 0; i < view.textListNode.children.length; ++i) {
28821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        let child = view.textListNode.children[i];
28921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (child.location && s(child.location)) {
29021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          if (firstSelect) {
29121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            makeContainerPosVisible(view.parentNode, child.offsetTop);
29221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch            firstSelect = false;
29321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          }
29421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          view.selection.select(child, selected);
29521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
29621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
29721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    } else if (s.length) {
29821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      for (let i of s) {
29921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        if (firstSelect) {
30021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          makeContainerPosVisible(view.parentNode, i.offsetTop);
30121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch          firstSelect = false;
30221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        }
30321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.selection.select(i, selected);
30421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
30521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    } else {
30621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (firstSelect) {
30721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        makeContainerPosVisible(view.parentNode, s.offsetTop);
30821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        firstSelect = false;
30921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
31021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.selection.select(s, selected);
31121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
31221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
31321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
31421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  mouseDownLine(li, e) {
31521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
31621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    e.stopPropagation();
31721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (!e.shiftKey) {
31821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.selection.clear();
31921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
32021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (li.location != undefined) {
32121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.selectLocations([li.location], true, false);
32221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
32321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
32421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
32521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  mouseDownSpan(span, e) {
32621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
32721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (view.allowSpanSelection) {
32821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      e.stopPropagation();
32921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (!e.shiftKey) {
33021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.selection.clear();
33121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
33221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      select(li, true);
33321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    } else if (span.link) {
33421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      span.link(span.textContent);
33521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      e.stopPropagation();
33621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
33721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
33821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
33921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  processText(text) {
34021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
34121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let textLines = text.split(/[\n]/);
34221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let lineNo = 0;
34321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    for (let line of textLines) {
34421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let li = document.createElement("LI");
34521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      li.onmousedown = function(e) {
34621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.mouseDownLine(li, e);
34721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
34821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      li.className = "nolinenums";
34921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      li.lineNo = lineNo++;
35021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let fragments = view.processLine(line);
35121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      for (let fragment of fragments) {
35221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.appendFragment(li, fragment);
35321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
35421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let lineLocation = view.lineLocation(li);
35521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (lineLocation != undefined) {
35621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        li.location = lineLocation;
35721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
35821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      view.textListNode.appendChild(li);
35921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
36021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
36121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
36221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  initializeContent(data, rememberedSelection) {
36321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
36421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.clearText();
36521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.processText(data);
36621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    var fillerSize = document.documentElement.clientHeight -
36721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        view.textListNode.clientHeight;
36821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (fillerSize < 0) {
36921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      fillerSize = 0;
37021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
37121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    view.fillerSvgElement.attr("height", fillerSize);
37221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
37321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
37421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  deleteContent() {
37521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
37621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
37721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  isScrollable() {
37821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return true;
37921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
38021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
38121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  detachSelection() {
38221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return null;
38321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
38421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
38521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  lineLocation(li) {
38621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    let view = this;
38721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    for (let i = 0; i < li.children.length; ++i) {
38821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      let fragment = li.children[i];
38921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (fragment.location != undefined && !view.allowSpanSelection) {
39021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch        return fragment.location;
39121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      }
39221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    }
39321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
39421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
395