function highlightLine(cm, line, state) {
    var mode = cm.view.mode, flattenSpans = cm.options.flattenSpans;
    var changed = !line.styles, pos = 0, curText = "", curStyle = null;
    var stream = new StringStream(line.text, cm.options.tabSize), st = line.styles || (line.styles = []);
    if (line.text == "" && mode.blankLine) mode.blankLine(state);
    while (!stream.eol()) {
      var style = mode.token(stream, state), substr = stream.current();
      stream.start = stream.pos;
      if (!flattenSpans || curStyle != style) {
        if (curText) {
          changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1];
          st[pos++] = curText; st[pos++] = curStyle;
        }
        curText = substr; curStyle = style;
      } else curText = curText + substr;
      // Give up when line is ridiculously long
      if (stream.pos > 5000) break;
    }
    if (curText) {
      changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1];
      st[pos++] = curText; st[pos++] = curStyle;
    }
    if (stream.pos > 5000) { st[pos++] = line.text.slice(stream.pos); st[pos++] = null; }
    if (pos != st.length) { st.length = pos; changed = true; }
    return changed;
  }