Merge changes Iec0be1c3,Iaa2a7653

* changes:
  sourcedr: Fix Prism line alignment problem
  sourcedr: Add temporary search
diff --git a/vndk/tools/source-deps-reviewer/sourcedr/preprocess.py b/vndk/tools/source-deps-reviewer/sourcedr/preprocess.py
index fc19d97..9176fec 100755
--- a/vndk/tools/source-deps-reviewer/sourcedr/preprocess.py
+++ b/vndk/tools/source-deps-reviewer/sourcedr/preprocess.py
@@ -206,7 +206,6 @@
         patt = re.compile(b'([^:]+):(\\d+):(.*)$')
         suspect = collections.defaultdict(list)
         for line in raw_grep.split(b'\n'):
-
             match = patt.match(line)
             if not match:
                 continue
@@ -265,21 +264,22 @@
         for pattern, is_regex in zip(patterns, is_regexs):
             if not is_regex:
                 pattern = re.escape(pattern)
-            try:
-                raw_grep = subprocess.check_output(
-                    ['csearch', '-n', pattern],
-                    cwd=os.path.expanduser(self.android_root),
-                    env=self.env)
-            except subprocess.CalledProcessError as e:
-                if e.output == b'':
-                    print('nothing found')
-                    return
+            raw_grep = self.raw_grep(pattern)
+            if raw_grep == b'':
+                continue
             processed += self.process_grep(raw_grep, pattern, is_regex)
         self.to_json(processed)
 
     def add_pattern(self, pattern, is_regex):
         if not is_regex:
             pattern = re.escape(pattern)
+        raw_grep = self.raw_grep(pattern)
+        if raw_grep == b'':
+            return
+        processed = self.process_grep(raw_grep, pattern, is_regex)
+        self.add_to_json(processed)
+
+    def raw_grep(self, pattern):
         try:
             raw_grep = subprocess.check_output(
                 ['csearch', '-n', pattern],
@@ -288,9 +288,13 @@
         except subprocess.CalledProcessError as e:
             if e.output == b'':
                 print('nothing found')
-                return
-        processed = self.process_grep(raw_grep, pattern, is_regex)
-        self.add_to_json(processed)
+                return b''
+        return raw_grep
+
+    def raw_search(self, pattern, is_regex):
+        if not is_regex:
+            pattern = re.escape(pattern)
+        return self.raw_grep(pattern)
 
     def to_json(self, processed):
         data = {}
diff --git a/vndk/tools/source-deps-reviewer/sourcedr/server.py b/vndk/tools/source-deps-reviewer/sourcedr/server.py
index 6cada2d..be4e323 100755
--- a/vndk/tools/source-deps-reviewer/sourcedr/server.py
+++ b/vndk/tools/source-deps-reviewer/sourcedr/server.py
@@ -6,9 +6,12 @@
 from flask import Flask, jsonify, render_template, request
 import argparse
 import bisect
+import collections
+from functools import cmp_to_key
 import hashlib
 import json
 import os
+import re
 import subprocess
 import sys
 import webbrowser
@@ -95,6 +98,48 @@
     save_new_pattern(patt, is_regex)
     return jsonify(result='done')
 
+
+# This function does a temporary grep to the directory
+# Not adding the result to database
+@app.route('/temporary_search')
+def _temporary_search():
+    path = request.args.get('path')
+    patt = request.args.get('pattern')
+    is_regex = request.args.get('is_regex')
+    result = engine.raw_search(patt, is_regex).decode('utf-8')
+    dic = collections.defaultdict(list)
+    patt = re.compile('([^:]+):(\\d+):(.*)$')
+    for line in result.split('\n'):
+        match = patt.match(line)
+        if not match:
+            continue
+
+        file_path = match.group(1)
+        line_no = match.group(2)
+        code = match.group(3)
+        dic[file_path].append((line_no, code))
+
+    def compare(item1, item2):
+        key1, value1 = item1
+        key2, value2 = item2
+        cnt1 = os.path.commonprefix([path, key1]).count('/')
+        cnt2 = os.path.commonprefix([path, key2]).count('/')
+        e1 = os.path.relpath(key1, path).count('/')
+        e2 = os.path.relpath(key2, path).count('/')
+        # prefer smaller edit distance
+        if e1 < e2: return -1
+        if e2 < e1: return 1
+        # prefer deeper common ancestor
+        if cnt1 > cnt2: return -1
+        if cnt2 > cnt1: return 1
+        # lexicographical order
+        if key1 < key2: return -1
+        if key2 < key1: return 1
+        return 0
+
+    result = sorted(dic.items(), key=cmp_to_key(compare))
+    return jsonify(result=json.dumps(result))
+
 @app.route('/')
 def render():
     return render_template('index.html')
diff --git a/vndk/tools/source-deps-reviewer/sourcedr/static/css/main.css b/vndk/tools/source-deps-reviewer/sourcedr/static/css/main.css
index 933f73a..11bb7bc 100644
--- a/vndk/tools/source-deps-reviewer/sourcedr/static/css/main.css
+++ b/vndk/tools/source-deps-reviewer/sourcedr/static/css/main.css
@@ -1,13 +1,26 @@
 h3, h4 {
-	display: inline-block;
+    display: inline-block;
 }
 
 pre {
-	white-space: pre-wrap;       /* Since CSS 2.1 */
-	white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
-	white-space: -pre-wrap;      /* Opera 4-6 */
-	white-space: -o-pre-wrap;    /* Opera 7 */
-	word-wrap: break-word;       /* Internet Explorer 5.5+ */
-	background-color: #ffffff;
-	margin: 0;
+    white-space: pre-wrap;       /* Since CSS 2.1 */
+    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
+    white-space: -pre-wrap;      /* Opera 4-6 */
+    white-space: -o-pre-wrap;    /* Opera 7 */
+    word-wrap: break-word;       /* Internet Explorer 5.5+ */
+    background-color: #ffffff;
+    margin: 0;
+}
+
+@media (min-width: 768px) {
+    .modal-xl {
+        width: 90%;
+        max-width:1200px;
+    }
+}
+
+.affix {
+  top:50px;
+  right:0;
+  position:fixed;
 }
diff --git a/vndk/tools/source-deps-reviewer/sourcedr/static/js/main.js b/vndk/tools/source-deps-reviewer/sourcedr/static/js/main.js
index e11d26c..db62041 100644
--- a/vndk/tools/source-deps-reviewer/sourcedr/static/js/main.js
+++ b/vndk/tools/source-deps-reviewer/sourcedr/static/js/main.js
@@ -37,6 +37,33 @@
     return pretag;
   }
 
+  function grepResultHtml(items) {
+    let ret = document.createElement('p');
+    for (let i = 0; i < items.length; i++) {
+      let path = document.createElement('span');
+      path.style.color = 'purple';
+      path.style.fontSize = '20px';
+      path.innerHTML = items[i][0];
+      ret.appendChild(path);
+      ret.appendChild(document.createElement('br'));
+      for (let j = 0; j < items[0][1].length; j++) {
+        let line_no = items[i][1][j][0];
+        let content = items[i][1][j][1];
+        let line_html = document.createElement('font');
+        line_html.style.color = 'green';
+        line_html.style.fontSize = '18px';
+        line_html.innerHTML = line_no + ':';
+        ret.appendChild(line_html);
+        let content_html = document.createElement('span');
+        content_html.style.fontSize = '18px';
+        content_html.appendChild(document.createTextNode(content));
+        ret.appendChild(content_html);
+        ret.appendChild(document.createElement('br'));
+      }
+    }
+    return ret;
+  }
+
   function enterTask() {
     let text = $('#enter_deps').val();
     $('#deps_list').append(taskHtml(text, counter));
@@ -104,7 +131,6 @@
       for (let i = 0; i < len; i++) {
         $('#pattern_list').append('<li>' + pattern_lst[i] + '</li>');
       }
-
       $('#path_prefix').text(data.path_prefix);
     });
   }
@@ -199,6 +225,7 @@
     setGotoPatternLine(line_no);
     $('#selected_text').val('');
     $('#code_file_path').val('');
+    $('#enter_deps').val('');
     $('html,body').scrollTop(0);
     return false;
   }
@@ -227,8 +254,30 @@
       pattern: values['pattern'],
       is_regex: $('#is_regex').is(':checked') ? 1 : 0
     });
+    return true;
+  });
+
+  $('#temporary_search').submit(function() {
+    const $inputs = $('#temporary_search :input');
+    let values = {};
+    $inputs.each(function () {
+      values[this.name] = $(this).val();
+    });
+    $('#modal_title').text(values['pattern']);
+    $.getJSON('/temporary_search', {
+      path: $('#file_path').text(),
+      pattern: values['pattern'],
+      is_regex: $('#is_regex2').is(':checked') ? 1 : 0
+    }, function (data) {
+        $('#modal_body').append(grepResultHtml(JSON.parse(data.result)));
+        $('#myModal').modal('show');
+    });
     return false;
   });
+  // clear previous html code in modal on hide
+  $('#myModal').on('hidden.bs.modal', function () {
+    $('#modal_body').empty();
+  })
 
   $('#add_deps').submit(enterTask);
   $('#add_code').submit(enterCode);
diff --git a/vndk/tools/source-deps-reviewer/sourcedr/static/prism/js/prism.js b/vndk/tools/source-deps-reviewer/sourcedr/static/prism/js/prism.js
index 758b01b..743a225 100644
--- a/vndk/tools/source-deps-reviewer/sourcedr/static/prism/js/prism.js
+++ b/vndk/tools/source-deps-reviewer/sourcedr/static/prism/js/prism.js
@@ -635,9 +635,17 @@
 	}
 }());
 
+function getOffsetById(id) {
+	var element = document.getElementById(id);
+	var bodyRect = document.body.getBoundingClientRect();
+	var elemRect = element.getBoundingClientRect();
+	var elementOffset = elemRect.top - bodyRect.top;
+	return elementOffset;
+}
+
 function highlightLines(pre, lines, classes) {
-	var ranges = lines.replace(/\s+/g, '').split(','),
-	    offset = +pre.getAttribute('data-line-offset') || 0;
+	var ranges = lines.replace(/\s+/g, '').split(',');
+	var offset = getOffsetById('browsing_file');
 
 	var parseMethod = isLineHeightRounded() ? parseInt : parseFloat;
 	var lineHeight = parseMethod(getComputedStyle(pre).lineHeight);
@@ -663,7 +671,7 @@
 			}
 		}
 
-		line.style.top = (start - offset - 1) * lineHeight + 'px';
+		line.style.top = (getOffsetById('line_no' + start) - offset) + 'px';
 
 		//allow this to play nicely with the line-numbers plugin
 		if(hasClass(pre, 'line-numbers')) {
@@ -734,33 +742,6 @@
 	}
 });
 
-Prism.hooks.add('complete', function(env) {
-	var pre = env.element.parentNode;
-	var lines = pre && pre.getAttribute('data-line');
-
-	if (!pre || !lines || !/pre/i.test(pre.nodeName)) {
-		return;
-	}
-
-	clearTimeout(fakeTimer);
-
-	highlightLines(pre, lines);
-
-	fakeTimer = setTimeout(applyHash, 1);
-});
-
-if(window.addEventListener) {
-	window.addEventListener('hashchange', applyHash);
-}
-
-})();
-
-(function() {
-
-if (typeof self === 'undefined' || !self.Prism || !self.document) {
-	return;
-}
-
 Prism.hooks.add('complete', function (env) {
 	if (!env.code) {
 		return;
@@ -795,8 +776,10 @@
 	var linesNum = match ? match.length + 1 : 1;
 	var lineNumbersWrapper;
 
-	var lines = new Array(linesNum + 1);
-	lines = lines.join('<span></span>');
+	var lines = '';
+	for (let i = 1; i < linesNum + 1; i++) {
+		lines += '<span id="line_no' + i + '"></span>';
+	}
 
 	lineNumbersWrapper = document.createElement('span');
 	lineNumbersWrapper.setAttribute('aria-hidden', 'true');
@@ -811,4 +794,31 @@
 
 });
 
+Prism.hooks.add('complete', function(env) {
+	var pre = env.element.parentNode;
+	var lines = pre && pre.getAttribute('data-line');
+
+	if (!pre || !lines || !/pre/i.test(pre.nodeName)) {
+		return;
+	}
+
+	clearTimeout(fakeTimer);
+
+	highlightLines(pre, lines);
+
+	fakeTimer = setTimeout(applyHash, 1);
+});
+
+if(window.addEventListener) {
+	window.addEventListener('hashchange', applyHash);
+}
+
+})();
+
+(function() {
+
+if (typeof self === 'undefined' || !self.Prism || !self.document) {
+	return;
+}
+
 }());
diff --git a/vndk/tools/source-deps-reviewer/sourcedr/templates/index.html b/vndk/tools/source-deps-reviewer/sourcedr/templates/index.html
index e46b3bf..9cf75ec 100644
--- a/vndk/tools/source-deps-reviewer/sourcedr/templates/index.html
+++ b/vndk/tools/source-deps-reviewer/sourcedr/templates/index.html
@@ -32,8 +32,17 @@
     </div>
     <br>
 
-    <div class="col-sm-4">
+    <div class="col-sm-4" data-spy="affix">
+
       <div class="well">
+        <h3>Temporary search</h3>
+        <form id="temporary_search" class="input-group" style="padding-left:20px;">
+          <span class="input-group-addon">is regex</span>
+          <span class="input-group-addon">
+            <input type="checkbox" name="is_regex2" id="is_regex2">
+          </span>
+          <input type="text" name="pattern" class="form-control">
+        </form>
         <h3>Add patterns to grep</h3>
         <form id="add_pattern" class="input-group" style="padding-left:20px;">
           <span class="input-group-addon">is regex</span>
@@ -43,12 +52,12 @@
           <input type="text" name="pattern" class="form-control">
         </form>
         <ul id="pattern_list"></ul>
-        <h3>File path:</h3>
+      </div>
+      <div class="well">
+        <h3>File labeling:</h3>
         <pre style="padding-left:20px;"><h4 id="file_path"></h4></pre>
         <h3>Pattern line number:</h3>
         <h3 id="line_no"></h3><br>
-      </div>
-      <div class="well">
         <h3>Library Dependencies</h3>
         <form id="add_deps" class="input-group">
           <input type="text" class="form-control" id="enter_deps" placeholder="Fill in * if undetermined"/>
@@ -57,15 +66,14 @@
           </span>
         </form>
         <ul id="deps_list"></ul>
-
         <h3>Code Dependencies</h3>
         <form id="add_code">
           <input class="btn btn-secondary" type="button" id="get_selection" value="Get selection"/>
           <input class="btn btn-secondary" type="submit" id="add_code" value="Add"/><br>
           <input type="text" id="code_file_path" style="margin: 0px; width: 100%;"/>
           <textarea id="selected_text" name="selectedtext" rows="5" style="margin: 0px; width: 100%; height: 106px;"></textarea>
-          <ul id="code_list"></ul>
         </form>
+        <ul id="code_list"></ul>
         <form id="save_all">
           <input class="btn btn-secondary" type="submit" value="Save All"/>
         </form>
@@ -74,11 +82,27 @@
   </div>
 </div>
 
+<!-- Modal -->
+<div class="modal fade" id="myModal" role="dialog">
+  <div class="modal-dialog modal-xl">
+    <!-- Modal content-->
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal">&times;</button>
+        <h4 id="modal_title" class="modal-title"></h4>
+      </div>
+      <div id="modal_body" class="modal-body">
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+      </div>
+    </div>
+  </div>
+</div>
 
 <script type="text/javascript" src="static/js/main.js"></script>
 <!-- for code prettyify -->
 <script src="static/prism/js/prism.js"></script>
-<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
 
 </body>
 </html>