Advertisement
Guest User

extSearch

a guest
Mar 22nd, 2017
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //engine: JScript
  2. //uname: ExtendedSearch
  3. //dname: Расширенный поиск
  4. //descr: Реализация удобного и мощного поиска по модулям.
  5. //author: Александр Кунташов <kuntashov@gmail.com>, http://compaud.ru/blog
  6. //www: https://snegopat.ru/scripts/wiki?name=extSearch.js
  7. //help: inplace
  8. //addin: global
  9. //addin: stdcommands
  10. //addin: stdlib
  11. //addin: hotkeys hks
  12.  
  13. ////////////////////////////////////////////////////////////////////////////////////////
  14. ////{ Cкрипт "Расширенный поиск" (extSearch.js) для проекта "Снегопат"
  15. ////
  16. //// Описание: Реализует поиск текста при помощи регулярных выражений в активном окне редактора.
  17. //// Автор: Александр Кунташов <kuntashov@gmail.com>, http://compaud.ru/blog
  18. ////}
  19. ////////////////////////////////////////////////////////////////////////////////////////
  20.  
  21. /*@
  22. Скрипт организует удобный поиск как по текущему модулю, так и глобальный поиск по конфигурации.
  23. Глобальный поиск выполняется в **фоновом режиме!** Вы можете работать, пока он ищет.
  24.  
  25. Поддерживается поиск с помощью регулярных выражений.
  26. Интегрирован со скриптом "Редактор регулярных выражений".
  27.  
  28. @*/
  29.  
  30. stdlib.require('TextWindow.js', SelfScript);
  31. stdlib.require('ScriptForm.js', SelfScript);
  32. global.connectGlobals(SelfScript);
  33.  
  34. ////////////////////////////////////////////////////////////////////////////////////////
  35. ////{ Макросы
  36. ////
  37.  
  38. SelfScript.self['macrosНайти текст'] = function() {
  39.    
  40.     var w = GetTextWindow();
  41.     if (!w) return false;
  42.    
  43.     var es = GetExtSearch();
  44.        
  45.     var selText = w.GetSelectedText();
  46.     if (selText == '')
  47.         selText = w.GetWordUnderCursor();
  48.    
  49.     es.setSimpleQuery(selText);    
  50.     es.show();
  51.        
  52.     if (selText == '')
  53.     {
  54.         es.clearSearchResults();
  55.         es.setDefaultSearchQuery();
  56.     }
  57.     else
  58.         es.searchActiveDoc(true);
  59.        
  60.     return true;
  61. }
  62.  
  63. SelfScript.self['macrosНайти во всех открытых документах'] = function() {
  64.    
  65.     var w = GetTextWindow();
  66.     if (!w) return false;
  67.    
  68.     var es = GetExtSearch();
  69.        
  70.     var selText = w.GetSelectedText();
  71.     if (selText == '')
  72.         selText = w.GetWordUnderCursor();
  73.    
  74.     es.setSimpleQuery(selText);    
  75.     es.show();
  76.        
  77.     if (selText == '')
  78.     {
  79.         es.clearSearchResults();
  80.         es.setDefaultSearchQuery();
  81.     }
  82.     else
  83.         es.searchOpenedWindows(true);
  84.        
  85.     return true;
  86. }
  87.  
  88. SelfScript.self['macrosГлобальный поиск'] = function() {
  89.    
  90.     var es = GetExtSearchGlobal();
  91.  
  92.     var w = GetTextWindow();
  93.     if (!w) {
  94.         var selText = '';
  95.     } else {
  96.         var selText = w.GetSelectedText();
  97.         if (selText == '')
  98.             selText = w.GetWordUnderCursor();
  99.     }
  100.    
  101.     es.isGlobalFind = true;
  102.     es.activeView = windows.getActiveView();
  103.     es.isInCurrentMdConteinerFind = false;
  104.     es.setSimpleQuery(selText);    
  105.     es.show();
  106.  
  107.     if (selText == '')
  108.     {
  109.         es.clearSearchResults();
  110.         es.setDefaultSearchQuery();
  111.     }
  112.     else
  113.         es.searchInMetadata(true);
  114.        
  115.     return true;
  116. }
  117.  
  118. SelfScript.self['macrosГлобальный поиск по текущему контейнеру'] = function() {
  119.     //Текущий контейнер метаданных определяем по активному окну.
  120.     //будет открыта внешняя обработка, занчит ищем глобально только по этой обработке.
  121.     //открыт cf файл или же cf базы данных и мы находимся в текстовом модуле определенной
  122.     //конфигурации, значит искать будет по текущей контейнеру.
  123.    
  124.    
  125.     var es = GetExtSearchGlobal();
  126.  
  127.    
  128.     var w = GetTextWindow();
  129.     if (!w) {
  130.         var selText = '';
  131.     } else {
  132.         var selText = w.GetSelectedText();
  133.         if (selText == '')
  134.             selText = w.GetWordUnderCursor();
  135.     }
  136.    
  137.    
  138.     es.isGlobalFind = true;
  139.     es.activeView = windows.getActiveView();
  140.     es.isInCurrentMdConteinerFind = true;
  141.     es.setSimpleQuery(selText);    
  142.     es.show();
  143.  
  144.     if (selText == '')
  145.     {
  146.         es.clearSearchResults();
  147.         es.setDefaultSearchQuery();
  148.     }
  149.     else
  150.         es.searchInMetadata(true);
  151.        
  152.     return true;
  153. }
  154.  
  155. SelfScript.self['macrosГл поиск фильтр по метаданным'] = function() {
  156.    
  157.     var es = GetExtSearchGlobal();
  158.     if (es.isGlobalFind){
  159.         md = stdlib.require(env.pathes.addins + 'mdNavigator.js');
  160.         if (es.filterByUUID){
  161.             es.vtMD = {};
  162.             es.filterByUUID = null;
  163.         }
  164.         es.filterByUUID = md.SelectMdUUID();
  165.     }
  166.     es.show();
  167.  
  168.     return true;
  169. }
  170.  
  171. SelfScript.self['macrosОтменить глобальный поиск'] = function() {
  172.     var es = GetExtSearchGlobal();
  173.     if (es.startGlobalSearch){
  174.         es.startGlobalSearch = false;
  175.     }
  176. }
  177.  
  178. //// МАКРОСЫ С ПРЕДВАРИТЕЛЬНЫМ ОТКРЫТИЕМ ДИАЛОГА ДЛЯ НАСТРОЙКИ ПАРАМЕТРОВ ПОИСКА
  179.  
  180. SelfScript.self['macrosНайти текст в текущем модуле (с диалогом)'] = function() {    
  181.     openSearchDialog(SearchAreas.ActiveWindow);
  182.     return true;
  183. }
  184.  
  185. SelfScript.self['macrosНайти текст в открытых окнах (с диалогом)'] = function() {    
  186.     openSearchDialog(SearchAreas.AllOpenedWindows);
  187.     return true;
  188. }
  189.  
  190. SelfScript.self['macrosГлобальный поиск (с диалогом)'] = function() {    
  191.     openSearchDialog(SearchAreas.Global);  
  192.     return true;
  193. }
  194.  
  195. //// МАКРОСЫ ДЛЯ УПРАВЛЕНИЯ ОКНОМ РЕЗУЛЬТАТОВ ПОИСКА
  196.  
  197. SelfScript.self['macrosОткрыть окно поиска'] = function() {
  198.     debugger
  199.     GetExtSearch().show();
  200. }
  201.  
  202. SelfScript.self['macrosОткрыть окно глобального поиска'] = function() {
  203.     GetExtSearchGlobal().show();
  204. }
  205.  
  206. SelfScript.self['macrosЗакрыть окно поиска'] = function() {
  207.     var es = GetExtSearch();
  208.     if (es.isOpen()) {
  209.         es.close();
  210.         return true;
  211.     }
  212.     es = GetExtSearchGlobal();
  213.     if (es.isOpen()) {
  214.         es.close();
  215.         return true;
  216.     }
  217.     return false;
  218. }
  219.  
  220. SelfScript.self['macrosПерейти к следующему совпадению'] = function() {
  221.     var es = GetExtSearch();
  222.     es.show();
  223.     es.moveRowCursor(true);
  224. }
  225.  
  226. SelfScript.self['macrosПерейти к предыдущему совпадению'] = function() {
  227.     var es = GetExtSearch();
  228.     es.show();
  229.     es.moveRowCursor(false);
  230. }
  231.  
  232. SelfScript.self['macrosСвернуть группировки'] = function() {
  233.     var es = GetExtSearch();
  234.     es.expandTree(true);
  235. }
  236.  
  237. SelfScript.self['macrosРазвернуть группировки'] = function() {
  238.     var es = GetExtSearch();
  239.     es.expandTree(false);
  240. }
  241.  
  242. /* Возвращает название макроса по умолчанию - вызывается, когда пользователь
  243. дважды щелкает мышью по названию скрипта в окне Снегопата. */
  244. function getDefaultMacros() {
  245.     return 'Открыть окно поиска';
  246. }
  247.  
  248. ////} Макросы
  249.  
  250. ////////////////////////////////////////////////////////////////////////////////////////
  251. ////{ ExtSearch - Расширенный поиск в тексте модуля.
  252. ////
  253.  
  254. var RowTypes = {
  255.     'SearchResult'  : 0, // Строка результата поиска.
  256.     'ProcGroup'     : 1, // Строка группы-процедуры (в режиме группировки по процедурам и функциям).
  257.     'FuncGroup'     : 2, // Строка группы-функции (в режиме группировки по процедурам и функциям).
  258.     'SearchDoc'     : 3  // Строка документа, в котором производится поиск.
  259. }
  260.  
  261. var RE = {
  262.     METHOD_START : /^\s*((?:procedure)|(?:function)|(?:процедура)|(?:функция))\s+([\wА-яёЁ\d]+)\s*\(/i,
  263.     METHOD_END : /((?:EndProcedure)|(?:EndFunction)|(?:КонецПроцедуры)|(?:КонецФункции))/i
  264. }
  265.  
  266. var SearchAreas = {
  267.     'ActiveWindow'      : 0, // В текущем модуле
  268.     'AllOpenedWindows'  : 1, // Во всех открытых окнах
  269.     'Global'            : 2, // Глобально (во всех модулях основной конфигурации)
  270.     'CurrentContainer'  : 3  // В текущем открытом контейнере (внешней обработке, конфигурации ИБ и т.п.)
  271. };
  272.  
  273. //[+] СофтЛаб:Brad  (19.02.2015)
  274. function getCurentTask() {
  275.    
  276.     var pflCurTask = 'Задачи/ТекущаяЗадача';
  277.    
  278.     var s = v8New("Структура","Задача,Описание","",""); 
  279.     profileRoot.createValue(pflCurTask, s, pflSnegopat)    
  280.     s = profileRoot.getValue(pflCurTask);
  281.    
  282.     return s.Задача;
  283. }
  284. // СофтЛаб:Brad  (19.02.2015)
  285.  
  286. /* Осуществляет поиск с предварительным открытием диалогового окна. */
  287. function openSearchDialog(initSearchArea) {
  288.    
  289.     if (!initSearchArea)
  290.         initSearchArea = SearchAreas.ActiveWindow;
  291.    
  292.     var w = GetTextWindow();    
  293.     if (!w) return false;
  294.            
  295.     var selText = w.GetSelectedText();
  296.     if (selText == '')
  297.         selText = w.GetWordUnderCursor();
  298.        
  299.     //[+] СофтЛаб:Brad  (19.02.2015)
  300.     if (selText == '') 
  301.         selText = getCurentTask();     
  302.     // СофтЛаб:Brad  (19.02.2015)
  303.        
  304.     var sDlg = new ExtSearchDialog(selText, initSearchArea);
  305.        
  306.     if (sDlg.show(true) == true)
  307.     {
  308.         var searchQuery = sDlg.getSearchQueryParams();
  309.        
  310.         if (searchQuery.Query == '')
  311.         {
  312.             var es = GetExtSearch();
  313.             es.clearSearchResults();
  314.             es.setDefaultSearchQuery();
  315.         }
  316.         else
  317.         {  
  318.             switch(sDlg.getSearchArea())
  319.             {
  320.             case SearchAreas.AllOpenedWindows:
  321.                 var es = GetExtSearch();
  322.                 es.setQuery(searchQuery);
  323.                 es.show();
  324.                 es.searchOpenedWindows(true);
  325.                 break;
  326.                
  327.             case SearchAreas.CurrentContainer:
  328.                 var es = GetExtSearchGlobal();
  329.                 es.isGlobalFind = true;
  330.                 es.activeView = windows.getActiveView();
  331.                 es.isInCurrentMdConteinerFind = true;
  332.                 es.setQuery(searchQuery);
  333.                 es.show();
  334.                 es.searchInMetadata(true);
  335.                 break;
  336.                
  337.             case SearchAreas.Global:
  338.                 var es = GetExtSearchGlobal();
  339.                 es.isGlobalFind = true;
  340.                 es.activeView = windows.getActiveView();
  341.                 es.isInCurrentMdConteinerFind = false;
  342.                 es.setQuery(searchQuery);
  343.                 es.show();
  344.                 es.searchInMetadata(true);         
  345.                 break;
  346.                
  347.             case SearchAreas.ActiveWindow:
  348.             default:
  349.                 var es = GetExtSearch();
  350.                 es.setQuery(searchQuery);
  351.                 es.show();
  352.                 es.searchActiveDoc(true);
  353.                 break;
  354.             }
  355.         }
  356.     }
  357. }
  358.  
  359. /* Реализует диалог настройки параметров поиска.*/
  360. ExtSearchDialog = ScriptForm.extend({
  361.  
  362.     settingsRootPath : SelfScript.uniqueName,
  363.    
  364.     settings : {
  365.         pflSnegopat : {
  366.             'IsRegExp'      : false, // Поиск регулярными выражениями.
  367.             'CaseSensetive' : false, // Учитывать регистр при поиске.
  368.             'WholeWords'    : false, // Поиск слова целиком.
  369.             'SearchHistory' : v8New('ValueList'), // История поиска.
  370.             'HistoryDepth'  : 15, // Количество элементов истории поиска.
  371.             'TreeView'      : false // Группировать результаты поиска по методам.            
  372.         }
  373.     },
  374.  
  375.     construct : function (query, initSearchArea) { 
  376.         this._super(env.pathes.addins + "extSearch.ssf");                
  377.         this.form.КлючСохраненияПоложенияОкна = "extSearch.dialog.js"
  378.         this.loadSettings();
  379.         this.form.Query = query;
  380.         this.form.SearchArea = initSearchArea;     
  381.     },
  382.    
  383.     getSearchQueryParams: function () {
  384.         var params = v8New('Structure');
  385.         params.Insert('Query',          this.form.Query);
  386.         params.Insert('WholeWords',     this.form.WholeWords);
  387.         params.Insert('CaseSensetive',  this.form.CaseSensetive);
  388.         params.Insert('IsRegExp',       this.form.IsRegExp);
  389.         return params;
  390.     },
  391.    
  392.     getSearchArea: function () {
  393.         return this.form.SearchArea;
  394.     },
  395.    
  396.     Form_OnClose : function () {
  397.         this.saveSettings();
  398.     },
  399.    
  400.     Query_StartListChoice : function (control, defaultHandler) {
  401.         control.val.ChoiceList = this.form.SearchHistory;
  402.     },
  403.    
  404.     btFind_Click: function (btn) {
  405.         this.close(true);
  406.     },
  407.    
  408.     btCancel_Click: function (btn) {
  409.         this.close(false);
  410.     },
  411.    
  412.     IsRegExp_OnChange : function(Элемент) {
  413.         if (this.form.IsRegExp)
  414.             this.form.WholeWords = false;
  415.     },
  416.  
  417.     WholeWords_OnChange : function(Элемент) {
  418.         if (this.form.WholeWords)
  419.             this.form.IsRegExp = false;
  420.     }
  421. }); // end of ExtSearchDialog
  422.  
  423. ExtSearch = ScriptForm.extend({
  424.  
  425.     ////////////////////////////////////////////////////////////////33////////////////////////
  426. ////{ TextWindowsWatcher - отслеживает активизацию текстовых окон и запоминает последнее.
  427. ////
  428.  
  429.    
  430.  
  431.  
  432.  
  433.     settingsRootPath : SelfScript.uniqueName,
  434.    
  435.     settings : {
  436.         pflSnegopat : {
  437.             'IsRegExp'      : false, // Поиск регулярными выражениями.
  438.             'CaseSensetive' : false, // Учитывать регистр при поиске.
  439.             'WholeWords'    : false, // Поиск слова целиком.
  440.             'SearchHistory' : v8New('ValueList'), // История поиска.
  441.             'HistoryDepth'  : 15, // Количество элементов истории поиска.
  442.             'TreeView'      : false // Группировать результаты поиска по методам.            
  443.         }
  444.     },
  445.  
  446.     construct : function (isExtend) {
  447.        
  448.         if (isExtend == undefined) isExtend = false;
  449.         this._super(env.pathes.addins + "extSearch.results.ssf");
  450.  
  451.        
  452.         this.startWatch();      
  453.         this.form.КлючСохраненияПоложенияОкна = "extSearch.js"
  454.         this.results = this.form.Controls.SearchResults.Value;
  455.         this.results.Columns.Add('_method');
  456.         this.results.Columns.Add('groupsCache');
  457.         this.results.Columns.Add('_object');
  458.         this.results.Columns.Add('_match');
  459.         this.results.Columns.Add('SortMetadata');
  460.        
  461.          
  462.         this.loadSettings();
  463.        
  464.         this.targetWindow = null;
  465.        
  466.         this.Icons = {
  467.             'Func': this.form.Controls.PicFunc.Picture,
  468.             'Proc': this.form.Controls.PicProc.Picture
  469.         }
  470.        
  471.         this.SearchDocRowFont = v8New('Font', undefined, undefined, true);
  472.         this.isGlobalFind = false;
  473.        
  474.         this.SetControlsVisible();
  475.         if (!isExtend) ExtSearch._instance = this;
  476.         this.timerId = 0;
  477.         this.lastActiveTextWindow = null;
  478.    
  479.     },
  480.  
  481.    
  482.        
  483.  
  484.         startWatch : function () {
  485.             {
  486.                 if (this.timerId)
  487.                     this.stopWatch();
  488.                 this.timerId = createTimer(500, this, 'onTimer');
  489.             }
  490.         },
  491.  
  492.  
  493.        getActiveTextWindow : function () {
  494.             if (this.lastActiveTextWindow && this.lastActiveTextWindow.IsActive())
  495.                 return this.lastActiveTextWindow;
  496.             return GetTextWindow();
  497.  
  498.         },
  499.  
  500.  
  501.  
  502.         stopWatch : function() {
  503.             if (!this.timerId)
  504.                 return;
  505.             killTimer(this.timerId);
  506.             this.timerId = 0;
  507.         },
  508.  
  509.        onTimer : function (timerId) {
  510.             var wnd = GetTextWindow();
  511.             if (wnd)
  512.                 this.lastActiveTextWindow = wnd;
  513.             else if (this.lastActiveTextWindow && !this.lastActiveTextWindow.IsActive())
  514.                 this.lastActiveTextWindow = null;
  515.         }
  516.     ,
  517. //} TextWindowsWatcher
  518.    
  519.     setSimpleQuery : function (query) {
  520.         this.form.Query = query;
  521.         this.form.IsRegExp = false;
  522.         this.form.CaseSensetive = false;
  523.         this.addToHistory(query);
  524.     },
  525.    
  526.     setQuery : function (searchQueryParams) {
  527.         this.form.Query         = searchQueryParams.Query;
  528.         this.form.IsRegExp      = searchQueryParams.IsRegExp;
  529.         this.form.CaseSensetive = searchQueryParams.CaseSensetive;
  530.         this.form.WholeWords    = searchQueryParams.WholeWords;
  531.         this.addToHistory(this.form.Query);
  532.     },
  533.  
  534.     expandTree : function (collapse) {
  535.         var tree = this.form.Controls.SearchResults;
  536.         for (var i=0; i < this.results.Rows.Count(); i++)
  537.         {        
  538.             var docRow = this.results.Rows.Get(i);
  539.             if (this.form.TreeView)
  540.             {
  541.                 for (var j=0; j < docRow.Rows.Count(); j++)
  542.                 {
  543.                     var row = docRow.Rows.Get(j);
  544.                     collapse ? tree.Collapse(row) : tree.Expand(row, true);
  545.                 }
  546.             }
  547.             else
  548.             {
  549.                 collapse ? tree.Collapse(docRow) : tree.Expand(docRow, true);            
  550.             }
  551.         }
  552.     },
  553.        
  554.     getWindowObject : function (view) {
  555.        
  556.         if (view.mdObj && view.mdProp)
  557.             return new MdObject(view.mdObj, view.mdProp, view.title);
  558.            
  559.         var obj = view.getObject();
  560.         if (obj && toV8Value(obj).typeName(0) == 'TextDocument')
  561.             return new TextDocObject(obj, view.title);        
  562.            
  563.         if (obj) Message('Неподдерживаемый тип объекта для поиска: ' + toV8Value(obj).typeName(0));
  564.        
  565.         return null;
  566.     },
  567.    
  568.     searchOpenedWindows: function (fromHotKey) {
  569.  
  570.         var activeWindow = this.getActiveTextWindow();
  571.         if (!activeWindow) return;
  572.        
  573.         var activeView = activeWindow.GetView();
  574.         if (!activeView) return;
  575.  
  576.         this.clearSearchResults();
  577.                      
  578.         this.re = this.buildSearchRegExpObject();
  579.         if (!this.re) return;
  580.        
  581.         var activeWndResRow = null;
  582.        
  583.         var es = this;
  584.         (function (views) {        
  585.             for(var i = 0; i < views.count; i++)
  586.             {
  587.                 var v = views.item(i);
  588.                 if(v.isContainer != vctNo)
  589.                 {
  590.                     // Если окно - контейнер, то обходим рекурсивно его потомков.
  591.                     arguments.callee(v.enumChilds());
  592.                     continue;
  593.                 }
  594.                                
  595.                 var obj = es.getWindowObject(v);
  596.                 if (!obj) continue;
  597.                
  598.                 var docRow = es.search(obj, es.re);
  599.                 if (v == activeView)
  600.                     activeWndResRow = docRow;
  601.             }
  602.         })(windows.mdiView.enumChilds());
  603.        
  604.         this.showSearchResult(activeWndResRow, fromHotKey);
  605.     },
  606.  
  607.     searchActiveDoc : function (fromHotKey) {
  608.        
  609.         this.clearSearchResults();
  610.        
  611.         var activeWindow = this.getActiveTextWindow();
  612.         if (!activeWindow) return;
  613.              
  614.         this.re = this.buildSearchRegExpObject();
  615.         if (!this.re) return;
  616.  
  617.         var obj = this.getWindowObject(activeWindow.GetView());
  618.         if (!obj) return;
  619.        
  620.         var docRow = this.search(obj, this.re);
  621.        
  622.         this.showSearchResult(docRow, fromHotKey);
  623.     },
  624.  
  625.     buildSearchRegExpObject : function () {
  626.    
  627.         var pattern = this.form.Query;
  628.         var reFlags = '';
  629.        
  630.         if (!this.form.IsRegExp)
  631.         {
  632.             pattern = StringUtils.addSlashes(pattern);
  633.            
  634.             if (this.form.WholeWords)
  635.                 pattern = "([^\\w\\dА-я]|^)" + pattern + "([^\\w\\dА-я]|$)";
  636.         }
  637.         else
  638.         {
  639.             if(pattern.replace("\\\\", "").search(/\\r|\\n/) != -1)
  640.                 reFlags = 'gm';
  641.         }
  642.         if(!this.form.CaseSensetive)
  643.             reFlags += 'i';
  644.        
  645.         var re = null;
  646.        
  647.         try
  648.         {
  649.             re = new RegExp(pattern, reFlags);
  650.         }
  651.         catch (e)
  652.         {
  653.             DoMessageBox("В регулярном выражении допущена ошибка: \n" + e.message);
  654.             return null;
  655.         }
  656.    
  657.         return re;
  658.     },
  659.    
  660.     search : function (obj, re) {
  661.          
  662.         var docRow = this.results.Rows.Add();
  663.         docRow.FoundLine = obj.getTitle();
  664.         docRow._object = obj;
  665.         docRow.RowType = RowTypes.SearchDoc;
  666.         if (!obj.sort) obj.sort = 999;
  667.         var strSort = "0000000000"+(obj.sort + this.results.Rows.Count());
  668.         strSort = strSort.substr(strSort.length-10);
  669.         docRow.SortMetadata = strSort;
  670.  
  671.         docRow.groupsCache = v8New('Map');
  672.         if(!re.multiline)
  673.         {
  674.             var curMethod = {
  675.                 'Name'      : 'Раздел описания переменных',
  676.                 'IsProc'    : undefined,
  677.                 'StartLine' : 0
  678.             }
  679.                                    
  680.             var lines = StringUtils.toLines(obj.getText());
  681.             for(var lineIx=0; lineIx < lines.length; lineIx++)
  682.             {
  683.                 var line = lines[lineIx];
  684.                
  685.                 // Проверим, не встретилось ли начало метода.
  686.                 var matches = line.match(RE.METHOD_START);
  687.                 if (matches && matches.length)
  688.                 {
  689.                     curMethod = {
  690.                         'Name'      : matches[2],
  691.                         'IsProc'    : matches[1].toLowerCase() == 'процедура' || matches[1].toLowerCase() == 'procedure',
  692.                         'StartLine' : lineIx
  693.                     }
  694.                 }
  695.                
  696.                 matches = line.match(re);
  697.                 if (matches && matches.length)
  698.                     this.addSearchResult(docRow, line, lineIx + 1, matches, curMethod);
  699.                    
  700.                 // Проверим, не встретился ли конец метода.
  701.                 matches = line.match(RE.METHOD_END);
  702.                 if (matches && matches.length)
  703.                 {
  704.                     curMethod = {
  705.                         'Name'      : '<Текст вне процедур и функций>',
  706.                         'IsProc'    : undefined,
  707.                         'StartLine' : lineIx
  708.                     }
  709.                 }
  710.             }    
  711.         }
  712.         else
  713.         {
  714.             //debugger
  715.             // Это многострочный поиск
  716.             // Для начала надо вообще проверить, находится ли что-нибудь
  717.             var text = obj.getText()
  718.             var results = [], r
  719.             while(r = re.exec(text))
  720.                 results.push(r)
  721.             if(results.length)  // Что-то нашли. Теперь надо получить номера строк для каждого вхождения
  722.             {
  723.                 this.form.TreeView = false;
  724.                 var idx = 0, lineNum = 0, currentRes = results[idx], beginIdx = currentRes.index
  725.                 // Для исключение ситуации, когда текст найден в последней строке, не заканчивающейся переводом строки,
  726.                 // добавим к тексту перевод строки
  727.                 text += '\n';
  728.                 re = /.*\n/g
  729.                 while(r = re.exec(text))
  730.                 {
  731.                     lineNum++
  732.                     if(r.index <= beginIdx && r.lastIndex > beginIdx)
  733.                     {
  734.                         currentRes.index -= r.index
  735.                         currentRes.lastIndex -= r.index
  736.                         // Для отображения результата многострочного поиска преобразуем строку
  737.                         currentRes.realResult = currentRes[0]
  738.                         currentRes[0] = currentRes[0].replace(/^\s+/, '').replace(/\n\s*/g, ' \u00BB ').substr(0, 50) + '\n'
  739.                         this.addSearchResult(docRow, r[0], lineNum, results[idx]);
  740.                         idx++;
  741.                         if(idx == results.length)
  742.                             break;
  743.                         currentRes = results[idx]
  744.                         beginIdx = currentRes.index
  745.                     }
  746.                 }
  747.             }
  748.         }
  749.        
  750.         if (this.form.TreeView && docRow.Rows.Count() > 0)
  751.         {
  752.             var lastGroup = this.results.Rows.Get(this.results.Rows.Count() - 1);
  753.             if (lastGroup.FoundLine == '<Текст вне процедур и функций>')
  754.                 lastGroup.FoundLine = "Раздел основной программы";
  755.         }
  756.        
  757.         if (!docRow.Rows.Count())
  758.         {
  759.             this.results.Rows.Delete(docRow);
  760.             docRow = null;
  761.         }
  762.        
  763.         return docRow;
  764.     },
  765.  
  766.     showResult: function(docRow, fromHotKey){
  767.         this.results.Rows.Sort('SortMetadata, FoundLine', false);
  768.         // Запомним строку поиска в истории.
  769.         this.addToHistory(this.form.Query);
  770.  
  771.         if (fromHotKey == true)
  772.         {
  773.             // Для того чтобы курсор не прыгал при поиске текущего слова,
  774.             // тут бы еще добавить чтобы активизировалась именно текущая строка
  775.             this.form.Open();
  776.             this.form.CurrentControl=this.form.Controls.SearchResults;
  777.             if (docRow)
  778.             {
  779.                 var curLineRow = this.getRowForTheCurrentLine(docRow);  
  780.                 if (curLineRow)
  781.                     this.form.Controls.SearchResults.CurrentRow = curLineRow;            
  782.             }
  783.         }
  784.         else if (docRow)
  785.         {
  786.             if (this.form.TreeView)
  787.                 this.goToLine(docRow.Rows.Get(0).Rows.Get(0));
  788.             else
  789.                 this.goToLine(docRow.Rows.Get(0));        
  790.         }
  791.  
  792.     },
  793.    
  794.     showSearchResult: function (docRow, fromHotKey) {
  795.        
  796.         this.showResult(docRow, fromHotKey);
  797.         this.expandTree();
  798.        
  799.         if (this.results.Rows.Count() == 0)
  800.         {
  801.             DoMessageBox('Совпадений не найдено!');
  802.             return;
  803.         }
  804.  
  805.         this.SetControlsVisible();    
  806.     },
  807.    
  808.     getRowForTheCurrentLine: function(docRow) {
  809.         var twnd = this.lastActiveTextWindow;
  810.         return docRow.Rows.Find(twnd.GetCaretPos().beginRow, "LineNo", true);
  811.     },
  812.  
  813.     getGroupRow: function (docRow, methodData) {
  814.  
  815.         if (!this.form.TreeView || this.re.multiline)
  816.             return docRow;
  817.  
  818.         var groupRow = docRow.groupsCache.Get(methodData);
  819.         if (!groupRow)
  820.         {
  821.             groupRow = docRow.Rows.Add();
  822.             groupRow.FoundLine = (!methodData.Name)?"":methodData.Name;
  823.             groupRow.Method = (!methodData.Name)?"":methodData.Name;
  824.             groupRow._object = docRow._object;
  825.            
  826.             if (methodData.IsProc !== undefined)
  827.                 groupRow.RowType = methodData.IsProc ? RowTypes.ProcGroup : RowTypes.FuncGroup;
  828.                
  829.             groupRow.lineNo = methodData.StartLine + 1;
  830.             groupRow._method = methodData;
  831.             groupRow.SortMetadata = methodData.SortMetadata;
  832.            
  833.             docRow.groupsCache.Insert(methodData, groupRow);
  834.         }
  835.         return groupRow;
  836.     },
  837.    
  838.     addSearchResult : function (docRow, line, lineNo, matches, methodData) {
  839.  
  840.         var groupRow = this.getGroupRow(docRow, methodData);
  841.  
  842.         var resRow = groupRow.Rows.Add();
  843.         resRow.FoundLine = line;
  844.         resRow.lineNo = lineNo;
  845.         resRow._object = docRow._object;
  846.         if(undefined != methodData)
  847.             resRow.Method = methodData.Name;
  848.  
  849.         resRow._method = methodData;
  850.         resRow._match = matches
  851.            
  852.         if (this.form.WholeWords)
  853.             resRow.ExactMatch = matches[0].replace(/^[^\w\dА-я]/, '').replace(/[^\w\dА-я]$/, '');
  854.         else
  855.             resRow.ExactMatch = matches[0];
  856.     },
  857.    
  858.     goToLine : function (row) {
  859.  
  860.         this.form.Controls.SearchResults.CurrentRow = row;    
  861.  
  862.         // Откроем и/или активируем окно объекта, в котором выполнялся поиск.
  863.         //var targetWindow = row._object.activate();
  864.      
  865.         //if (!targetWindow.IsActive())
  866.         // {
  867.          //   DoMessageBox("Окно, для которого выполнялся поиск, было закрыто!\nОкно поиска с результатами стало не актуально и будет закрыто.");
  868.          //   this.clearSearchResults();
  869.          //   this.Close();
  870.          //   return;
  871.         // }
  872.      
  873.         // Найдем позицию найденного слова в строке.
  874.         //debugger
  875.         var lineStart = row.LineNo, colStart, lineEnd = lineStart, colEnd
  876.         if(row.ExactMatch.substr(row.ExactMatch.length - 1) == '\n')
  877.         {
  878.             // результат многострочного поиска
  879.             var text = row._match.realResult
  880.             colStart = row._match.index + 1
  881.             colEnd = colStart
  882.             for(var k = 0; k < text.length; k++)
  883.             {
  884.                 if(text.charAt(k) == '\n')
  885.                 {
  886.                     lineEnd++
  887.                     colEnd = 1;
  888.                 }
  889.                 else
  890.                     colEnd++
  891.             }
  892.         }
  893.         else
  894.         {
  895.             var searchPattern = this.form.WholeWords ? "(?:[^\\w\\dА-я]|^)" + row.ExactMatch + "([^\\w\\dА-я]|$)" : StringUtils.addSlashes(row.ExactMatch);
  896.             var re = new RegExp(searchPattern, 'g');
  897.             var matches = re.exec(row.FoundLine);
  898.  
  899.             colStart = 1;
  900.             if (matches)
  901.             {        
  902.                 colStart = re.lastIndex - row.ExactMatch.length + 1;
  903.                
  904.                 if (this.form.WholeWords && matches.length > 1)        
  905.                     colStart -= matches[1].length;
  906.             }
  907.             colEnd = colStart + row.ExactMatch.length
  908.         }
  909.        
  910.         // Установим выделение на найденное совпадение со строкой поиска.
  911.         var targetWindow = this.lastActiveTextWindow;
  912.         if (!targetWindow) return;
  913.         targetWindow._view.activate();
  914.         targetWindow.SetCaretPos(lineStart, colEnd);
  915.         targetWindow.SetSelection(lineStart, colStart, lineEnd, colEnd);
  916.        
  917.     },
  918.  
  919.     moveRowCursor : function (forward) {
  920.        
  921.         if (!this.results.Rows.Count())
  922.             return;
  923.                          
  924.         var row = this.form.Controls.SearchResults.CurrentRow;
  925.        
  926.         if (!row)
  927.         {
  928.             row = this.results.Rows.Get(0).Get(0);
  929.             if (this.form.TreeView)
  930.                 row = row.Rows.Get(0);
  931.                
  932.             this.goToLine(row);    
  933.             return;
  934.         }
  935.        
  936.         if (forward)
  937.         {
  938.             if (row.RowType == RowTypes.SearchResult)
  939.             {    
  940.                 while (row)
  941.                 {
  942.                     var rows = row.Parent ? row.Parent.Rows : this.results.Rows;
  943.                     var index = rows.IndexOf(row);
  944.            
  945.                     if (index < rows.Count() - 1)
  946.                     {
  947.                         row = rows.Get(index + 1);
  948.                         break;
  949.                     }
  950.                    
  951.                     if (!row.Parent)
  952.                         break;
  953.                    
  954.                     row = row.Parent;                    
  955.                  }
  956.             }
  957.            
  958.             while (row.Rows.Count() > 0)
  959.                 row = row.Rows.Get(0);                        
  960.         }
  961.         else
  962.         {  
  963.             if (row.RowType == RowTypes.SearchResult)
  964.             {    
  965.                 while (row)
  966.                 {
  967.                     var rows = row.Parent ? row.Parent.Rows : this.results.Rows;
  968.                     var index = rows.IndexOf(row);
  969.            
  970.                     if (index > 0)
  971.                     {
  972.                         row = rows.Get(index - 1);
  973.                         break;
  974.                     }
  975.                    
  976.                     if (!row.Parent)
  977.                         break;
  978.                    
  979.                     row = row.Parent;                    
  980.                  }
  981.             }
  982.            
  983.             while (row.Rows.Count() > 0)
  984.                 row = row.Rows.Get(row.Rows.Count() - 1);                        
  985.         }
  986.        
  987.         this.goToLine(row);
  988.     },
  989.    
  990.     clearSearchResults : function () {
  991.         this.results.Rows.Clear();
  992.     },
  993.    
  994.     setDefaultSearchQuery : function () {
  995.         this.form.CurrentControl=this.form.Controls.Query;
  996.     },
  997.    
  998.     addToHistory : function (query) {
  999.        
  1000.         if (!query)
  1001.             return;
  1002.        
  1003.         // Добавляем в историю только если такой поисковой строки там нет.
  1004.         var history = this.form.SearchHistory;
  1005.         if (history.FindByValue(query))
  1006.             return;
  1007.            
  1008.         if (history.Count())
  1009.             history.Insert(0, query);
  1010.         else
  1011.             history.Add(query);
  1012.            
  1013.         // Не позволяем истории расти более заданной глубины.
  1014.         while (history.Count() > this.form.HistoryDepth)
  1015.             history.Delete(history.Count() - 1);
  1016.     },
  1017.    
  1018.     getRegExpEditorScriptPath : function () {
  1019.         var mainFolder = profileRoot.getValue("Snegopat/MainFolder");
  1020.         var scriptPath = mainFolder + "scripts\\RegExpEditor.js";
  1021.         var f = v8New('File', scriptPath);
  1022.         if (f.Exist())
  1023.             return scriptPath;
  1024.         return '';
  1025.     },
  1026.    
  1027.     Form_OnOpen : function () {  
  1028.         if (!this.getRegExpEditorScriptPath())
  1029.             this.form.Controls.Query.ChoiceButton = false;
  1030.        
  1031.         this.SetControlsVisible();
  1032.     },
  1033.  
  1034.     Form_OnClose : function () {
  1035.         this.saveSettings();
  1036.     },
  1037.  
  1038.     CmdBar_BtPrev : function (control) {
  1039.         this.moveRowCursor(false);
  1040.     },
  1041.  
  1042.     CmdBar_BtNext : function (control) {
  1043.         this.moveRowCursor(true);
  1044.     },
  1045.    
  1046.     Query_OnChange : function (control) {
  1047.         if (this.form.Query != '')
  1048.                 this.searchActiveDoc();
  1049.     },
  1050.  
  1051.     Query_StartListChoice : function (control, defaultHandler) {
  1052.         control.val.ChoiceList = this.form.SearchHistory;
  1053.     },
  1054.  
  1055.     BtSearch_Click : function (control) {
  1056.  
  1057.         if (this.form.Query == '')
  1058.         {
  1059.             DoMessageBox('Не задана строка поиска');
  1060.             return;
  1061.         }
  1062.        
  1063.         this.searchActiveDoc();
  1064.     },
  1065.  
  1066.     CmdBarOptions_BtAbout : function (control) {
  1067.         RunApp('http://snegopat.ru/scripts/wiki?name=extSearch.js');
  1068.     },
  1069.  
  1070.     SearchResults_Selection : function (control, selectedRow, selectedCol, defaultHandler) {
  1071.         this.goToLine(selectedRow.val);
  1072.         defaultHandler.val = false; // Это для того чтобы после нажатия на строку курсор не уходит с табличного поля, и при новой активизации формы можно было курсором посмотреть другие значения
  1073.     },
  1074.    
  1075.     beforeExitApp : function () {
  1076.         this.stopWatch();
  1077.     },
  1078.  
  1079.     IsRegExp_OnChange : function(Элемент) {
  1080.         if (this.form.IsRegExp)
  1081.             this.form.WholeWords = false;
  1082.  
  1083.         this.SetControlsVisible()
  1084.     },
  1085.  
  1086.     WholeWords_OnChange : function(Элемент) {
  1087.         if (this.form.WholeWords)
  1088.             this.form.IsRegExp = false;
  1089.  
  1090.         this.SetControlsVisible();
  1091.     },
  1092.    
  1093.     Query_StartChoice : function (Control, DefaultHandler) {
  1094.         var reEditorPath = this.getRegExpEditorScriptPath();
  1095.         if (reEditorPath)
  1096.         {
  1097.             DefaultHandler.val = false;
  1098.             reEditorAddin = stdlib.require(reEditorPath);
  1099.             if (reEditorAddin)
  1100.             {
  1101.                 this.form.IsRegExp = true;
  1102.                 var reEditor = reEditorAddin.CreateRegExpEditor();
  1103.                 reEditor.open(Control.val);
  1104.             }        
  1105.         }
  1106.     },
  1107.    
  1108.     SearchResults_OnRowOutput : function (Control, RowAppearance, RowData) {
  1109.        
  1110.         var cell = RowAppearance.val.Cells.FoundLine;
  1111.        
  1112.         switch (RowData.val.RowType)
  1113.         {
  1114.         case RowTypes.FuncGroup:
  1115.             cell.SetPicture(this.Icons.Func);
  1116.             break;
  1117.        
  1118.         case RowTypes.ProcGroup:
  1119.             cell.SetPicture(this.Icons.Proc);
  1120.             break;
  1121.  
  1122.         case RowTypes.SearchDoc:
  1123.             RowAppearance.val.Cells.LineNo.SetText('');
  1124.             RowAppearance.val.Font = this.SearchDocRowFont;
  1125.             RowAppearance.val.TextColor = WebColors.DarkBlue;
  1126.             break;
  1127.            
  1128.         default:
  1129.             break;
  1130.         }
  1131.        
  1132.         if (RowData.val._method && RowData.val._method.IsProc !== undefined)
  1133.             RowAppearance.val.Cells.Method.SetPicture(RowData.val._method.IsProc ? this.Icons.Proc : this.Icons.Func);
  1134.        
  1135.     },
  1136.    
  1137.     switchView : function (setTreeView) {
  1138.        
  1139.         var results = this.results.Copy();
  1140.        
  1141.         this.clearSearchResults();
  1142.        
  1143.         for (var docRowIx = 0; docRowIx < results.Rows.Count(); docRowIx++)
  1144.         {
  1145.             var oldDocRow = results.Rows.Get(docRowIx);
  1146.             var docRow = this.results.Rows.Add();
  1147.             FillPropertyValues(docRow, oldDocRow);
  1148.             docRow.groupsCache = v8New('Map');
  1149.            
  1150.             if (setTreeView)
  1151.             {
  1152.                 for (var i=0; i<oldDocRow.Rows.Count(); i++)
  1153.                 {
  1154.                     var row = oldDocRow.Rows.Get(i);
  1155.                     var groupRow = this.getGroupRow(docRow, row._method);
  1156.                     var resRow = groupRow.Rows.Add();
  1157.                     FillPropertyValues(resRow, row);
  1158.                 }
  1159.             }
  1160.             else
  1161.             {
  1162.                 for (var i=0; i<oldDocRow.Rows.Count(); i++)
  1163.                 {
  1164.                     var groupRow = oldDocRow.Rows.Get(i);
  1165.                     for (var j=0; j<groupRow.Rows.Count(); j++)
  1166.                     {
  1167.                         var row = groupRow.Rows.Get(j);
  1168.                         var resRow = docRow.Rows.Add();
  1169.                         FillPropertyValues(resRow, row);
  1170.                     }
  1171.                 }
  1172.             }    
  1173.         }
  1174.         this.expandTree();        
  1175.         this.SetControlsVisible();
  1176.     },
  1177.    
  1178.     CmdBar_TreeView : function (Button) {
  1179.         this.form.TreeView = !this.form.TreeView;
  1180.         Button.val.Check = this.form.TreeView;
  1181.         //this.form.Controls.SearchResults.Columns.FoundLine.ShowHierarchy = this.form.TreeView;
  1182.         this.switchView(this.form.TreeView);
  1183.     },
  1184.    
  1185.     CmdBar_ExpandAll : function (Button) {
  1186.         this.expandTree(false);
  1187.     },
  1188.    
  1189.     CmdBar_CollapseAll : function (Button) {
  1190.         this.expandTree(true);
  1191.     },
  1192.  
  1193.     SetControlsVisible : function() {
  1194.        
  1195.         var ctr = this.form.Controls;
  1196.         //ctr.SearchResults.Columns.FoundLine.ShowHierarchy = this.form.TreeView;    
  1197.         ctr.CmdBar.Buttons.TreeView.Check = this.form.TreeView;
  1198.         this.form.Controls.SearchResults.Columns.Method.Visible = !this.form.TreeView;
  1199.         this.form.Controls.SearchResults.Columns.ExactMatch.Visible = this.form.IsRegExp;
  1200.  
  1201.         var buttons = this.form.Controls.CmdBar.Buttons;
  1202.         buttons.ExpandAll.Enabled = this.form.TreeView;
  1203.         buttons.Actions.Buttons.ExpandAll.Enabled = this.form.TreeView;
  1204.         buttons.CollapseAll.Enabled = this.form.TreeView;
  1205.         buttons.Actions.Buttons.CollapseAll.Enabled = this.form.TreeView;
  1206.  
  1207.         this.form.caption = "Расширенный поиск в модуле";
  1208.     }
  1209.  
  1210. }); // end of ExtSearch class
  1211.  
  1212. ExtSearchGlobal = ExtSearch.extend({
  1213.  
  1214.     settingsRootPath : SelfScript.uniqueName+"Global", // тест, пускай у нас и настройки будут глобальными.
  1215.    
  1216.     settings : {
  1217.         pflSnegopat : {
  1218.             'IsRegExp'      : false, // Поиск регулярными выражениями.
  1219.             'CaseSensetive' : false, // Учитывать регистр при поиске.
  1220.             'WholeWords'    : false, // Поиск слова целиком.
  1221.             'SearchHistory' : v8New('ValueList'), // История поиска.
  1222.             'HistoryDepth'  : 15, // Количество элементов истории поиска.
  1223.             'TreeView'      : false // Группировать результаты поиска по методам.            
  1224.         }
  1225.     },
  1226.  
  1227.     construct : function () {
  1228.    
  1229.         this._super(true);
  1230.  
  1231.         this._instance = null;
  1232.  
  1233.         this.form.КлючСохраненияПоложенияОкна = "extGlobalSearch.js";
  1234.  
  1235.         this.isGlobalFind = true;
  1236.         //TODO: признак автомтически назначаемого хоткей, если уже назначен на отмену поиска, автоматом не будет назначаться.
  1237.         this.dynamicHotKey = true;
  1238.         for(var i = 0; i < hotkeys.count; i++)
  1239.         {
  1240.             var hk = hotkeys.item(i);
  1241.             Команда = hk.addin + "::" + hk.macros
  1242.             if (Команда.indexOf("ExtendedSearch::Отменить глобальный поиск")!=-1){
  1243.                 this.dynamicHotKey = false;
  1244.                 break;
  1245.             }
  1246.         }
  1247.        
  1248.         this.expandetRows = {};
  1249.        
  1250.         this.SetControlsVisible();
  1251.         //FIXME: вынести в настройку.
  1252.         this.countRowsInIdleSearch = 25; //Количество объектов поиска в фоне(для слабеньких машин ставим меньше, для формула1 - как удобней)
  1253.         this.re = new RegExp(/(([а-яa-z0-9]{1,})\s[а-яa-z0-9]{1,})(\.|\:)/i);
  1254.            
  1255.         this.filterByUUID = null;
  1256.  
  1257.         ExtSearchGlobal._instance = this;
  1258.     },
  1259.  
  1260.     searchByUuid: function(row, sort) {
  1261.         mdObj = findMdObj(this.currentMdContainer, row.UUID);
  1262.         if (sort == undefined) sort = 999;
  1263.         var docRow = null;
  1264.         if (mdObj){
  1265.             var obj = this.getWindowObject({
  1266.                                 mdObj:mdObj,
  1267.                                 mdProp:row.mdProp,
  1268.                                 title:row.title});
  1269.             obj.sort = sort+1;
  1270.             docRow = this.search(obj, this.re);
  1271.         }
  1272.         return docRow;
  1273.     },
  1274.    
  1275.     searchInMetadata : function(fromHotKey){
  1276.  
  1277.         var md = null;
  1278.         var objTitle = "";
  1279.         var activeWindow = this.getActiveTextWindow();
  1280.         if (!activeWindow) {
  1281.         } else {
  1282.             var activeView = activeWindow.GetView();
  1283.             var obj = this.getWindowObject(activeView);
  1284.             if (obj!=null){
  1285.                 objTitle = obj.getTitle();
  1286.                 var matches = this.re.exec(objTitle);
  1287.                 if (matches!=null){
  1288.                     objTitle = matches[1];
  1289.                 } else {
  1290.                     if (objTitle.indexOf(":")!=-1){
  1291.                         objTitle = objTitle.substr(0, objTitle.indexOf(":"));
  1292.                     }
  1293.                 }
  1294.             }
  1295.         }
  1296.  
  1297.         md = this.getCurrentMd();
  1298.         if (!md) return;
  1299.  
  1300.         this.currentMdContainer = md;
  1301.         this.clearSearchResults();
  1302.         this.re = this.buildSearchRegExpObject();
  1303.         if (!this.re) return;
  1304.        
  1305.         this.curCaption = windows.caption; //а вдруг, еще кто-то не пользуется configCaption...
  1306.        
  1307.         this.startGlobalSearch = true;
  1308.         if (!this.vtMD){
  1309.             this.vtMD = {};
  1310.         }
  1311.         this.reatingMdObjects = {"ОбщийМодуль":2,
  1312.                                 "Конфигурация":3,
  1313.                                 "ПланОбмена":4,
  1314.                                 "ОбщаяФорма":5
  1315.                             };
  1316.         if (objTitle.length>0){
  1317.             this.reatingMdObjects[objTitle]=1; //Самый высокий рейтинг...    
  1318.         }
  1319.        
  1320.  
  1321.         this.readMdToVt(this.currentMdContainer);
  1322.         this.expandetRows = {};
  1323.         this.curId = 0;
  1324.         if (this.dynamicHotKey)
  1325.             hks.AddHotKey("Ctrl+Shift+BkSpace", "ExtendedSearch", "Отменить глобальный поиск");
  1326.         events.connect(Designer, "onIdle", this);
  1327.        
  1328.         //this.showSearchResult(docRow, fromHotKey);
  1329.         //windows.caption = curCaption;
  1330.     },
  1331.  
  1332.     getCurrentMd:function(){
  1333.         var md ;
  1334.         if (this.isInCurrentMdConteinerFind ) {
  1335.             if (!this.activeView){
  1336.                 var activeWindow = this.getActiveTextWindow();    
  1337.                 if (!activeWindow){
  1338.                 } else {
  1339.                     var activeView = activeWindow.GetView();    
  1340.                 }
  1341.             } else {
  1342.  
  1343.                 var activeView = this.activeView;    
  1344.             }
  1345.             //Определим объект конфигурации по текущему окну.
  1346.             if (!activeView) {
  1347.             } else {
  1348.                 if (activeView.mdObj && activeView.mdProp) {
  1349.                     md = activeView.mdObj.container;
  1350.                 } else if (activeView.mdObj) {
  1351.                     md = activeView.mdObj.container;
  1352.                 }
  1353.             }
  1354.            
  1355.         }
  1356.        
  1357.         if (!md) {
  1358.             md = metadata.current;  
  1359.         }
  1360.  
  1361.         return md;
  1362.     },
  1363.    
  1364.     onIdle:function(){
  1365.         if (!this.startGlobalSearch) {
  1366.             windows.caption = this.curCaption;
  1367.             events.disconnect(Designer, "onIdle", this);
  1368.             this.showSearchResult(docRow, false);
  1369.             this.expandetRows = {};
  1370.            
  1371.             if (this.dynamicHotKey) {
  1372.                 for(var i = 0; i < hotkeys.count; i++)
  1373.                 {
  1374.                     var hk = hotkeys.item(i);
  1375.                     Команда = hk.addin + "::" + hk.macros
  1376.                     if (Команда.indexOf("ExtendedSearch::Отменить глобальный поиск")!=-1){
  1377.                         try {
  1378.                             hotkeys.remove(i);
  1379.                         } catch (e) {}
  1380.                     }
  1381.                 }
  1382.             }
  1383.             return;
  1384.         }
  1385.         var currentId = this.currentMdContainer.rootObject.id;
  1386.         if (this.vtMD[currentId].Count()<1) {
  1387.             this.startGlobalSearch = false;
  1388.             events.disconnect(Designer, "onIdle", this);
  1389.             return;
  1390.         }
  1391.        
  1392.         var count = 0;
  1393.         var docRow = null;
  1394.         while (count < this.countRowsInIdleSearch){
  1395.             if (this.curId<this.vtMD[currentId].Count()){
  1396.                 //docRow = this.searchByUuid(this.vtMD[currentId][this.curId]);
  1397.                 var currRow = this.vtMD[currentId].Get(this.curId);
  1398.                 docRow = this.searchByUuid(currRow, this.curId);
  1399.                 windows.caption = currRow.mdName;
  1400.             } else {
  1401.                 this.startGlobalSearch = false;
  1402.                 break;
  1403.             }
  1404.             this.curId ++;
  1405.             count++;
  1406.         }
  1407.         this.showSearchResult(null, false);
  1408.        
  1409.     },
  1410.    
  1411.     readMdToVt:function(MdContainer){
  1412.         var currentId = MdContainer.rootObject.id;
  1413.         if (!this.vtMD[currentId]){
  1414.             var docRow = null;
  1415.             //this.vtMD[currentId] = [];
  1416.             this.vtMD[currentId]=v8New("ValueTable");
  1417.             this.vtMD[currentId].Columns.Add("UUID");
  1418.             this.vtMD[currentId].Columns.Add("mdProp");
  1419.             this.vtMD[currentId].Columns.Add("mdName");
  1420.             this.vtMD[currentId].Columns.Add("title");
  1421.             this.vtMD[currentId].Columns.Add("sortTitle");
  1422.             this.vtMD[currentId].Columns.Add("sort");
  1423.             this.vtMD[currentId].Columns.Add("LineNumber");
  1424.  
  1425.             var es = this;
  1426.             //Реквизиты пропустим
  1427.             var ignoredMdClass = {
  1428.                 "Реквизиты":"",
  1429.                 "Макеты" : "" ,
  1430.                 "ОбщиеКартинки" : "" ,
  1431.                 "Элементы стиля" : "" ,
  1432.                 "Подсистемы" : "" ,
  1433.                 "Языки" : "" ,
  1434.                 "Стили" : "" ,
  1435.                 "Интерфейсы" : "" ,
  1436.                 "ПараметрыСеанса" : "" ,
  1437.                 "Роли" : "" ,
  1438.                 "ОбщиеМакеты" : "" ,
  1439.                 "КритерииОтбора" : "" ,
  1440.                 "ОбщиеРеквизиты" : "" ,
  1441.                 "ТабличныеЧасти" : "" ,
  1442.                 "Параметры" : ""
  1443.                 };
  1444.                
  1445.             var LineNumber = 0; //Для сортировки модулей функций по порядку обхода, а не по алфавиту.
  1446.            
  1447.             (function (mdObj){
  1448.                 if (!es.startGlobalSearch) {return}
  1449.                
  1450.                 var mdc = mdObj.mdclass;
  1451.            
  1452.                 function getMdName(mdObj) {                            
  1453.                     if (mdObj.parent && mdObj.parent.mdClass.name(1) != 'Конфигурация')
  1454.                         return getMdName(mdObj.parent) + '.' + mdObj.mdClass.name(1) + ' ' + mdObj.name;
  1455.                     var cname = mdObj.mdClass.name(1);
  1456.                     return  (cname ? cname + ' ' : '') + mdObj.name;
  1457.                 }
  1458.                 var mdName = getMdName(mdObj)
  1459.                
  1460.                 for(var i = 0, c = mdc.propertiesCount; i < c; i++){
  1461.                     var mdProp = mdc.propertyAt(i);
  1462.                     var mdPropName = mdc.propertyAt(i).name(1);
  1463.  
  1464.                     if (mdObj.isPropModule(mdProp.id)){
  1465.                         //var row = {UUID : mdObj.id}
  1466.                         var row = es.vtMD[currentId].Add();
  1467.                         row.UUID = mdObj.id;
  1468.                         row.mdProp = mdProp;
  1469.                         row.mdName = mdName;
  1470.                        
  1471.                         LineNumber++;
  1472.                         var title = mdName + ': ' + mdPropName;
  1473.                         row.title = title;
  1474.  
  1475.                         row.sort = 9;
  1476.                         row.LineNumber = LineNumber;
  1477.                         var matches;
  1478.  
  1479.                         var re = new RegExp(/(([а-яa-z0-9]{1,})\s[а-яa-z0-9]{1,})(\.|:)/i);
  1480.                        
  1481.                         matches = re.exec(mdName);
  1482.                         if (matches!=null){
  1483.                             row.sortTitle = matches[1];
  1484.  
  1485.                             if (!es.reatingMdObjects[matches[1]]){
  1486.                                 if (!es.reatingMdObjects[matches[2]]) {
  1487.                                     row.sort = 9;
  1488.                                } else {
  1489.                                     row.sort = es.reatingMdObjects[matches[2]];
  1490.                                }
  1491.                             } else {
  1492.                                 row.sort = es.reatingMdObjects[matches[1]];  
  1493.                             }
  1494.                                
  1495.                            
  1496.                         }                        
  1497.                        
  1498.                     }
  1499.                 }
  1500.                 // Перебираем классы потомков (например у Документа это Реквизиты, ТабличныеЧасти, Формы)
  1501.                 for(var i = 0; i < mdc.childsClassesCount; i++)
  1502.                 {
  1503.                     var childMdClass = mdc.childClassAt(i)
  1504.                    
  1505.                     if (!(ignoredMdClass[childMdClass.name(1, true)]==undefined)){
  1506.                         continue;
  1507.                     }
  1508.                    
  1509.                     // Для остального переберем потомков этого класса.
  1510.                     for(var chldidx = 0, c = mdObj.childObjectsCount(i); chldidx < c; chldidx++){
  1511.                         var childObject = mdObj.childObject(i, chldidx);
  1512.                         arguments.callee(childObject);
  1513.                     }
  1514.                 }
  1515.                 })(MdContainer.rootObject)
  1516.            
  1517.         } else {
  1518.             for (var key in this.reatingMdObjects){
  1519.                 if (this.reatingMdObjects[key]<2) {
  1520.                     var filter = v8New("Structure");
  1521.                     filter.Insert("sort", 1);
  1522.            
  1523.                     var findRows = this.vtMD[currentId].FindRows(filter);
  1524.                     if (findRows.Count()>0){
  1525.                         for (var i=0; i<findRows.Count(); i++){
  1526.                             var currRow = findRows.Get(i);
  1527.                             if (currRow.sortTitle != key){
  1528.                                 currRow.sort = 9;
  1529.                             }
  1530.                         }
  1531.                     }
  1532.  
  1533.                     var filter = v8New("Structure");
  1534.                     filter.Insert("sortTitle", key);
  1535.                     var findRows = this.vtMD[currentId].FindRows(filter);
  1536.                     if (findRows.Count()>0){
  1537.                         for (var i=0; i<findRows.Count(); i++){
  1538.                             var currRow = findRows.Get(i);
  1539.                             if (currRow.sortTitle != key){
  1540.                                 currRow.sort = (!this.reatingMdObjects[key]) ? 9: this.reatingMdObjects[key];
  1541.                             }
  1542.                         }
  1543.                     }                    
  1544.                 }
  1545.                
  1546.                
  1547.             }
  1548.            
  1549.         }
  1550.  
  1551.         if (this.filterByUUID){
  1552.             var arrayToFilter = v8New('Array');
  1553.             var firstElement = false;
  1554.             for (var k in this.filterByUUID){
  1555.                 firstElement = true;
  1556.                 var filter = v8New("Structure");
  1557.                 filter.Insert("UUID", k);
  1558.                 var findRows = this.vtMD[currentId].FindRows(filter);
  1559.                 if (findRows.Count()>0){
  1560.                     for (var i=0; i<findRows.Count(); i++){
  1561.                         arrayToFilter.Add(findRows.Get(i));
  1562.                     }
  1563.                 }
  1564.             }
  1565.             if (firstElement)
  1566.                 this.vtMD[currentId] = this.vtMD[currentId].Copy(arrayToFilter);
  1567.  
  1568.         }
  1569.         this.vtMD[currentId].Sort("sort, LineNumber, title");
  1570.  
  1571.     },
  1572.    
  1573.  
  1574.     Query_OnChange : function(Control){
  1575.  
  1576.         return;
  1577.  
  1578.     },
  1579.  
  1580.     BtSearch_Click : function (control) {
  1581.  
  1582.         if (this.form.Query == '')
  1583.         {
  1584.             DoMessageBox('Не задана строка поиска');
  1585.             return;
  1586.         }
  1587.  
  1588.         this.searchInMetadata(true);
  1589.     },
  1590.  
  1591.  
  1592.     SetControlsVisible : function(){
  1593.         this._super();
  1594.         if (this.isGlobalFind){
  1595.             this.form.caption = "Расширенный поиск в модуле (глобальный)";
  1596.         }
  1597.     },
  1598.  
  1599.     showSearchResult: function (docRow, fromHotKey) {
  1600.         this.showResult(docRow, fromHotKey);
  1601.         this.expandTree();
  1602.     },
  1603.    
  1604.     expandTree : function (collapse) {
  1605.         var tree = this.form.Controls.SearchResults;
  1606.         for (var i=0; i < this.results.Rows.Count(); i++)
  1607.         {        
  1608.             var docRow = this.results.Rows.Get(i);
  1609.             if (this.form.TreeView)
  1610.             {
  1611.                 for (var j=0; j < docRow.Rows.Count(); j++)
  1612.                 {
  1613.                     var row = docRow.Rows.Get(j);
  1614.                     if (this.expandetRows[""+row.LineNo+row.FoundLine]){
  1615.                         continue;
  1616.                     }
  1617.                     collapse ? tree.Collapse(row) : tree.Expand(row, true);
  1618.                     if (this.startGlobalSearch){
  1619.                         this.expandetRows[""+row.LineNo+row.FoundLine] = "1";
  1620.                     }
  1621.                 }
  1622.             }
  1623.             else
  1624.             {
  1625.                 if (this.expandetRows[""+docRow.LineNo+docRow.FoundLine]){
  1626.                     continue;
  1627.                 }
  1628.                 collapse ? tree.Collapse(docRow) : tree.Expand(docRow, true);            
  1629.                
  1630.                 if (this.startGlobalSearch){
  1631.                     this.expandetRows[""+docRow.LineNo+docRow.FoundLine] = "1";
  1632.                 }
  1633.             }
  1634.         }
  1635.     }
  1636.      
  1637.  
  1638.  
  1639. })
  1640.  
  1641. ////} ExtSearch
  1642.  
  1643. ////////////////////////////////////////////////////////////////////////////////////////
  1644. ////{ Вспомогательные объекты.
  1645. ////
  1646.  
  1647. MdObject = stdlib.Class.extend({          
  1648.     construct: function (obj, prop, title) {
  1649.         this.obj = obj;
  1650.         this.prop = prop;
  1651.         this.title = title;
  1652.     },
  1653.     getText: function() {
  1654.         return this.obj.getModuleText(this.prop.id);
  1655.     },
  1656.     activate: function() {
  1657.         this.obj.openModule(this.prop.id);
  1658.         return GetTextWindow();
  1659.     },
  1660.     getTitle: function() {
  1661.         if (!this.title)
  1662.         {
  1663.             function getMdName(mdObj) {                            
  1664.                 if (mdObj.parent && mdObj.parent.mdClass.name(1) != 'Конфигурация')
  1665.                     return getMdName(mdObj.parent) + '.' + mdObj.mdClass.name(1) + ' ' + mdObj.name;
  1666.                 var cname = mdObj.mdClass.name(1);
  1667.                 return  (cname ? cname + ' ' : '') + mdObj.name;
  1668.             }
  1669.             this.title = getMdName(this.obj) + ': ' + this.prop.name(1);
  1670.         }
  1671.         return this.title;
  1672.     }
  1673. });
  1674.  
  1675. TextDocObject = stdlib.Class.extend({
  1676.     construct: function (txtDoc, title) {
  1677.         this.obj = txtDoc;
  1678.         this.title = title;
  1679.     },
  1680.     getText: function() {
  1681.         return this.obj.GetText();
  1682.     },
  1683.     activate: function() {
  1684.         this.obj.Show();
  1685.         return GetTextWindow();
  1686.     },
  1687.     getTitle: function() {
  1688.         if (!this.title)
  1689.             this.title = this.obj.UsedFileName;
  1690.         return this.title;
  1691.     }
  1692. });
  1693.  
  1694. function findMdObj(currentmd, uuid)
  1695. {
  1696.     if(uuid == currentmd.rootObject.id)
  1697.         return currentmd.rootObject
  1698.     return currentmd.findByUUID(uuid);
  1699. }
  1700. ////
  1701. ////} Вспомогательные объекты.
  1702. ////////////////////////////////////////////////////////////////////////////////////////
  1703.  
  1704.  
  1705. ////////////////////////////////////////////////////////////////////////////////////////
  1706. ////{ StartUp
  1707. ////
  1708. function GetExtSearch() {
  1709.     if (!ExtSearch._instance)
  1710.         new ExtSearch();
  1711.    
  1712.     return ExtSearch._instance;
  1713. }
  1714.  
  1715. function GetExtSearchGlobal() {
  1716.     if (!ExtSearchGlobal._instance)
  1717.         new ExtSearchGlobal();
  1718.    
  1719.     return ExtSearchGlobal._instance;
  1720. }
  1721.  
  1722.  
  1723. events.connect(Designer, "beforeExitApp", GetExtSearch());
  1724. events.connect(Designer, "beforeExitApp", GetExtSearchGlobal());
  1725. ////}
  1726.  
  1727. function getMacrosInfo(name, info) {
  1728.     if (name == "Найти текст") {
  1729.         info.descr =  "Поиск текста в открытом документе";
  1730.         info.picture = stdcommands.Frame.Search.info.picture;
  1731.     } else if (name == "Глобальный поиск") {
  1732.         info.descr =  "Запустить поиск по конфигурации";
  1733.         info.picture = stdcommands.Frame.SearchGlobal.info.picture;
  1734.     }
  1735. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement