diff --git a/ctl/ctlSQLBox.cpp b/ctl/ctlSQLBox.cpp index 6b6630b..cf31a94 100644 --- a/ctl/ctlSQLBox.cpp +++ b/ctl/ctlSQLBox.cpp @@ -21,10 +21,13 @@ #include "ctl/ctlSQLBox.h" #include "dlg/dlgFindReplace.h" #include "frm/menu.h" +#include "frm/frmMain.h" #include "utils/sysProcess.h" #include #include #include "utils/align/AlignWrap.h" +#include "utils/popuphelp.h" + wxString ctlSQLBox::sqlKeywords; static const wxString s_leftBrace(_T("([{")); static const wxString s_rightBrace(_T(")]}")); @@ -43,6 +46,7 @@ wxString pgscriptKeywords = wxT(" assert break columns continue date datetime fi BEGIN_EVENT_TABLE(ctlSQLBox, wxStyledTextCtrl) EVT_KEY_DOWN(ctlSQLBox::OnKeyDown) EVT_MENU(MNU_FIND, ctlSQLBox::OnSearchReplace) + EVT_MENU(MNU_FUNC_HELP, ctlSQLBox::OnFuncHelp) EVT_MENU(MNU_COPY, ctlSQLBox::OnCopy) EVT_MENU(MNU_AUTOCOMPLETE, ctlSQLBox::OnAutoComplete) EVT_KILL_FOCUS(ctlSQLBox::OnKillFocus) @@ -194,11 +198,12 @@ void ctlSQLBox::Create(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons SetFoldFlags(16); // Setup accelerators - wxAcceleratorEntry entries[3]; + wxAcceleratorEntry entries[4]; entries[0].Set(wxACCEL_CTRL, (int)'F', MNU_FIND); entries[1].Set(wxACCEL_CTRL, WXK_SPACE, MNU_AUTOCOMPLETE); entries[2].Set(wxACCEL_CTRL, (int)'C', MNU_COPY); - wxAcceleratorTable accel(3, entries); + entries[3].Set(wxACCEL_CTRL, WXK_F1, MNU_FUNC_HELP); + wxAcceleratorTable accel(4, entries); SetAcceleratorTable(accel); // Autocompletion configuration @@ -497,9 +502,41 @@ void ctlSQLBox::SetDefFunction(wxArrayString &name, wxArrayString &def) { void ctlSQLBox::OnCopy(wxCommandEvent& ev) { Copy(); } +void ctlSQLBox::OnFuncHelp(wxCommandEvent& ev) { + + FunctionPGHelper *fh=winMain->GetFunctionPGHelper(); + int pos = GetCurrentPos(); + if (!fh->isValid()) return; + wxPoint p = ClientToScreen( PointFromPosition(pos)); + wxString current = GetSelectedText(); + wxString key = ""; + if (!current.IsEmpty()) + key = current; + else { + wxChar ch; + wxString tmp; + while ((pos--) >= 0) + { + ch = GetCharAt(pos); + if (ch < 35) { break; } + if ( wxIsalnum(ch) || ch=='_' || ch> 255) tmp.Append(ch); + //pos--; + } + + for (int i = tmp.Len()-1; i >=0; i--) key+=tmp[i]; + } + delete m_PopupHelp; + m_PopupHelp = new popuphelp(this->GetParent(), key.Lower(), fh); + if (m_PopupHelp && m_PopupHelp->IsValid()) { + m_PopupHelp->Position(p, wxSize(0, 17)); + m_PopupHelp->Popup(); + } + +} void ctlSQLBox::OnKeyDown(wxKeyEvent &event) { + if (event.GetKeyCode() == WXK_ESCAPE && m_PopupHelp) { delete m_PopupHelp; m_PopupHelp = NULL; } int pos = GetCurrentPos(); wxChar ch = GetCharAt(pos - 1); wxChar nextch = GetCharAt(pos); diff --git a/include/ctl/ctlSQLBox.h b/include/ctl/ctlSQLBox.h index 7cb9f77..503eb33 100644 --- a/include/ctl/ctlSQLBox.h +++ b/include/ctl/ctlSQLBox.h @@ -21,6 +21,7 @@ #include "db/pgConn.h" #include "dlg/dlgFindReplace.h" #include "ctl/ctlAuiNotebook.h" +#include "utils/popuphelp.h" // These structs are from Scintilla.h which isn't easily #included :-( struct CharacterRange @@ -57,6 +58,7 @@ public: void OnAutoComplete(wxCommandEvent &event); void OnSearchReplace(wxCommandEvent &event); void OnCopy(wxCommandEvent& ev); + void OnFuncHelp(wxCommandEvent& ev); void OnKillFocus(wxFocusEvent &event); // void OnBackGround(wxEraseEvent &event); void SetQueryBook(ctlAuiNotebook *query_book); @@ -121,6 +123,7 @@ private: wxArrayString *m_def; // finction arguments wxString list_table; // list table from section wxString calltip; + popuphelp *m_PopupHelp=NULL; int ct_hl; dlgFindReplace *m_dlgFindReplace; pgConn *m_database; diff --git a/include/frm/frmMain.h b/include/frm/frmMain.h index d8b7cdc..1a94ad5 100644 --- a/include/frm/frmMain.h +++ b/include/frm/frmMain.h @@ -27,6 +27,7 @@ #include "frm/frmLog.h" #include "ctl/ctlGitPanel.h" #include "ctl/ctlShortCut.h" +#include "utils/FunctionPGHelper.h"; // // This number MUST be incremented if changing any of the default perspectives // @@ -180,6 +181,10 @@ public: { return pluginsMenu; } + FunctionPGHelper * GetFunctionPGHelper() + { + return &hhelp; + } wxString GetCurrentNodePath(); bool SetCurrentNode(wxTreeItemId node, const wxString &path); @@ -212,6 +217,7 @@ private: #if !defined(NO_WXJSON_GIT) ctlGitPanel* git; #endif + FunctionPGHelper hhelp; ctlAuiNotebook *listViews; ctlSQLBox *sqlPane; wxMenu *newMenu, *debuggingMenu, *reportMenu, *toolsMenu, *pluginsMenu, *viewMenu, diff --git a/include/frm/menu.h b/include/frm/menu.h index 0378a86..ca2aa09 100644 --- a/include/frm/menu.h +++ b/include/frm/menu.h @@ -96,6 +96,7 @@ enum MNU_CONTENTS, MNU_HELP, + MNU_FUNC_HELP, MNU_HINT, MNU_CONFIGSUBMENU, diff --git a/include/utils/FunctionPGHelper.h b/include/utils/FunctionPGHelper.h new file mode 100644 index 0000000..0f81d05 --- /dev/null +++ b/include/utils/FunctionPGHelper.h @@ -0,0 +1,139 @@ + +#ifndef FUNCTIONPGHELPER_H +#define FUNCTIONPGHELPER_H +#include +#include +#include +#include +#include +#include +#include + +extern sysSettings *settings; + +class FunctionPGHelper +{ +public: + FunctionPGHelper() {}; + wxString getHelpString(wxString fnd, bool isPart = true) { + if (!isValid()) return wxEmptyString; + auto search = body.find(fnd); + wxString txt; + + if (search != body.end()) + txt = search->second; + else + { + std::vector list; + int l = fnd.Len(); + wxString b; + for (const auto& e : body) { + if (e.first.Len() > l && e.first.StartsWith(fnd)) { + list.push_back(e.first); + b = e.second; + } + } + if (list.size() == 1) txt = b; + else { + for (const auto& s : list) { + txt += wxString::Format("%s
", s, s); + } + } + } + //if (i == wxNOT_FOUND) return wxEmptyString; + return txt; + } + wxString getSqlCommandHelp(wxString fnd) { + wxUniChar sep = wxFileName::GetPathSeparator(); + fnd.Replace(" ", ""); + wxString f = wxFindFirstFile(path + sep+"sql-"+fnd+"*.html"); + wxString last,txt; + + int c = 0; + while (!f.empty()) + { + f = f.AfterLast(sep); + last = f; + txt += wxString::Format("%s
", f, f); + f = wxFindNextFile(); + c++; + } + if (last.empty()) { + return wxEmptyString; + } + else if (c==1) { + return getHelpFile(last); + } + else { + return txt; + } + + } + wxString getHelpFile(wxString filename) { + wxString tempDir = path + wxFileName::GetPathSeparator() + filename; + if (!wxFileExists(tempDir)) return wxEmptyString; + wxTextFile tfile; + tfile.Open(tempDir); + // read the first line + wxString str, sbody; + sbody = tfile.GetFirstLine(); + bool flag = true; + wxRegEx b("()"); + while (!tfile.Eof()) + { + str = tfile.GetNextLine(); + if (flag && b.Matches(str)) { + size_t start, len; + b.GetMatch(&start, &len, 0); + str = str.Mid(start + len); + sbody = ""; + flag = false; + } + sbody += str; + } + return sbody; + + } + bool isValid() { + if (!isload) loadfile(); + return isload; + } +private: + bool isload = false; + wxString path; + std::map body; + void loadfile() { + if (isload) return; + body.clear(); + path = settings->GetPgHelpPath(); + wxString tempDir = path + "_func.txt"; + //tempDir="C:\\Users\\lsv\\Source\\Repos\\wxHtmlhint\\1"; + if (!wxFileExists(tempDir)) return; + wxTextFile tfile; + tfile.Open(tempDir); + + // read the first line + wxString str, sbody; + wxString name = tfile.GetFirstLine(); + + //wxSortedArrayString names; + name = name.AfterFirst('#'); + // read all lines one by one + // until the end of the file + while (!tfile.Eof()) + { + str = tfile.GetNextLine(); + if (str.Left(1) == '#') { + body.emplace(name, sbody); + sbody = ""; + name = str.AfterFirst('#'); + } + else sbody += str; + } + body.emplace(name, sbody); + isload = true; + }; + +}; + +#endif diff --git a/include/utils/popuphelp.h b/include/utils/popuphelp.h new file mode 100644 index 0000000..52c6055 --- /dev/null +++ b/include/utils/popuphelp.h @@ -0,0 +1,128 @@ +#ifndef POPUPHELP_H +#define POPUPHELP_H + +#include "wx/popupwin.h" +#include +#include "wx/clipbrd.h" +#include "utils/FunctionPGHelper.h" +#include +#include +#include + +class popuphelp : + public wxPopupTransientWindow +{ +public: + //popuphelp(wxWindow* parent); + bool ProcessLeftDown(wxMouseEvent& event) + { + return false; + } + bool IsValid() { + return isvalid; + } + popuphelp(wxWindow* parent,wxString keyword, FunctionPGHelper *hhelper) : wxPopupTransientWindow(parent) { + SetSize(450,370); + this->hhelper = hhelper; + SetBackgroundColour(*wxBLACK); + htmlWindow = new wxHtmlWindow(this, -1, wxDefaultPosition,GetSize()); + htmlWindow->SetRelatedStatusBar(0); + //htmlWindow->SetPage("

TEST

Set Page Works"); + wxString txt = hhelper->getHelpString(keyword); + if (txt.IsEmpty()) { + + txt = hhelper->getSqlCommandHelp(keyword); + if (txt.empty()) { + isvalid = false; + return; + } + } + SetPage(txt); + //wxSize sz= htmlWindow->GetSize(); + //sz = htmlWindow->GetBestSize(); + //htmlWindow->SetHTMLBackgroundImage(wxBitmapBundle::FromSVGFile("data/bg.svg", wxSize(65, 45))); + wxBoxSizer* topsizer; + topsizer = new wxBoxSizer(wxVERTICAL); + + //htmlWindow->SetInitialSize(wxSize(htmlWindow->GetInternalRepresentation()->GetWidth(), htmlWindow->GetInternalRepresentation()->GetHeight())); + + //SetSize(wxSize(300,150)); + topsizer->Add(htmlWindow, 1, wxALL, 1); + + //wxButton* bu1 = new wxButton(this, wxID_OK, _("OK")); + //bu1->SetDefault(); + + //topsizer->Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15); + + SetSizer(topsizer); + topsizer->Fit(this); + + //this->Bind(wxEVT_HTML_CELL_CLICKED, [&](wxHtmlCellEvent& event) { + // wxHtmlCell* c = event.GetCell(); + // + // wxString ctext=c->ConvertToText(NULL); + // ctext=htmlWindow->SelectionToText(); + // wxString s = wxString::Format("cell = %s",ctext.c_str()); + // wxMessageBox(s, "cell", wxOK | wxICON_INFORMATION); + + // }); + this->Bind(wxEVT_HTML_LINK_CLICKED, [&](wxHtmlLinkEvent& event) { + wxHtmlLinkInfo i = event.GetLinkInfo(); + wxString name = i.GetHref(); + wxString body=this->hhelper->getHelpString(name); + if (body.IsEmpty()) { + body = this->hhelper->getHelpFile(name); + } + SetPage(body); + //ctext=htmlWindow->SelectionToText(); + //wxString s = wxString::Format("cell = %s",ctext.c_str()); + }); + htmlWindow->Bind(wxEVT_RIGHT_UP, [&](wxMouseEvent& event) { + wxString name; + //wxString body = this->hhelper->getHelpString(name); + wxString ctext = htmlWindow->SelectionToText(); + if (!ctext.IsEmpty()) { + wxClipboardLocker clip; + if (!clip || + !wxTheClipboard->AddData(new wxTextDataObject(ctext))) + { + + } + Hide(); + return; + } + this->SetPage("", true); + //ctext=htmlWindow->SelectionToText(); + //wxString s = wxString::Format("cell = %s",ctext.c_str()); + }); + + } +private: + bool isvalid = true; + wxHtmlWindow* htmlWindow; + FunctionPGHelper* hhelper; + std::vector hist; + void SetPage(wxString innerbody,bool gethistory=false) { + wxString h; + int p = innerbody.Find(""); + if (p > -1) { + innerbody.Replace("", "", false); + h = "" + innerbody + ""; + } else + h = "" + innerbody + ""; + + if (gethistory) { + if (hist.size() < 2) { + Hide(); + return; + } + hist.pop_back(); + h = hist[hist.size()-1]; + } + else { + hist.push_back(h); + } + htmlWindow->SetPage(h); + } +}; +#endif diff --git a/include/version.h b/include/version.h index 4e5afce..fa705d9 100644 --- a/include/version.h +++ b/include/version.h @@ -13,10 +13,17 @@ #define VERSION_H // Application Versions +#ifdef CORP +#define VERSION_STR wxT("1.22") +#define VERSION_NUM 1,22,0,0 +#define VERSION_PACKAGE 1.22.2 +#else #define VERSION_STR wxT("1.26 Dev ASUTP support PG16") #define VERSION_NUM 1,26,0,0 #define VERSION_PACKAGE 1.26.0-dev +#endif + #define PRERELEASE 1 // #define BUILD "..." diff --git a/utils/_extract_func_help.pl b/utils/_extract_func_help.pl new file mode 100644 index 0000000..4342928 --- /dev/null +++ b/utils/_extract_func_help.pl @@ -0,0 +1,355 @@ +#!/usr/bin/perl + +use strict; +use Data::Dump qw(dump); +my $pathdir_help="."; +my @files; +my @stak; +my %function_help; + +my %useref; +my %section; +my %ignorehtml=( +'pgbench.html', + +); + +my @keys=( + "" + ,"" +); +my %tags=( +'pclass="func_signature"' => '', +'pclass="func_signature"/p' => '', +'p' => '
', +'p/p' => '
', +'ul' => '
    ', +'ul/ul' => '
', +'liclass="listitem"' => '
  • ', +'liclass="listitem"/li' => '
  • ', +'divclass="itemizedlist"' => '', +'divclass="itemizedlist"/div' => '', +'a' => '', +'a/a' => '', +'sup' => '', +'sup/sup' => '', +'em' => '', +'em/em' => '', +'emclass="replaceable"' => '', +'emclass="replaceable"/em' => '', +'emclass="lineannotation"' => '', +'emclass="lineannotation"/em' => '', +'spanclass="lineannotation"' => '', +'spanclass="lineannotation"/span' => '', +'acronymclass="acronym"' => '', +'acronymclass="acronym"/acronym' => '', + +'spanclass="quote"' => '', +'spanclass="quote"/span' => '', +'spanclass="productname"' => '', +'spanclass="productname"/span' => '', +'spanclass="emphasis"' => '', +'spanclass="emphasis"/span' => '', +'spanclass="refentrytitle"' => '', +'spanclass="refentrytitle"/span' => '', + +'spanclass="symbol_font"' => '', +'spanclass="symbol_font"/span' => '', +'code' => '', +'code/code' => '', +'preclass="programlisting"' => '
    ',
    +'preclass="programlisting"/pre'                 => '
    ', +'preclass="screen"' => '
    ',
    +'preclass="screen"/pre'                 => '
    ', +'preclass="synopsis"' => '', +'preclass="synopsis"/pre' => '', +'spanclass="optional"' => '', +'spanclass="optional"/span' => '', +'spanclass="systemitem"' => '', +'spanclass="systemitem"/span' => '', +'spanclass="application"' => '', +'spanclass="application"/span' => '', +'codeclass="filename"' => '', +'codeclass="filename"/code' => '', + +'emclass="parameter"' => '', +'emclass="parameter"/em' => '', +'emclass="firstterm"' => '', +'emclass="firstterm"/em' => '', + +'codeclass="varname"' => '', +'codeclass="varname"/code' => '', +'codeclass="structname"' => '', +'codeclass="structname"/code' => '', +'codeclass="structfield"' => '', +'codeclass="structfield"/code' => '', +'codeclass="literal"' => '', +'codeclass="literal"/code' => '', +'codeclass="function"' => '', +'codeclass="function"/code' => '', +'codeclass="returnvalue"' => '', +'codeclass="returnvalue"/code' => '', +'codeclass="type"' => '', +'codeclass="type"/code' => '', +'codeclass="command"' => '', +'codeclass="command"/code' => '', + +); +opendir(DIR, $pathdir_help) or die "can't opendir $pathdir_help: $!"; + +while (defined(my $file = readdir(DIR))) { + next if (!($file =~ /html$/)); + push @files, $file; +} +closedir(DIR); +my $TDcount=0; +foreach my $file (sort @files) { +#open my $info, $file or die "Could not open $file: $!"; +if (exists $ignorehtml{$file}) {next;} + +my $fileContent; +open(my $F, '<', $file) or die $!; +binmode($F); +{ + local $/; + $fileContent = <$F>; +} +close($F); +my $pos=0; +my $lvl=0; +my $cc=0; +my $val=""; +my $se="div"; + #div id=href + $pos=0; + while ($pos>-1) { + my $n1=index($fileContent,"id=\"",$pos); + if ($n1 > -1) { + my $n2=index($fileContent,"\"",$n1+4); + my $id_name=substr($fileContent,$n1+4,$n2-$n1-4); + my $nn=$n1; + while (substr($fileContent,$nn,1) ne "<") { + $nn--; + } + $nn++; + ($se)= substr($fileContent,$nn,40) =~ /(\S+)/; + + #print "se=$se id_name=$id_name tag=\n40 sim=".substr($fileContent,$nn,40); + $n2++; + $pos=$n2; + #if (exists $ref{$id_name}) + if (uc($id_name) eq $id_name) + { + my @st=(); + my $n3=$pos; + + while ($n1 > -1) { + $n1=$pos; + $n1=index($fileContent,$se,$pos); + if ($n1 >-1) { + #print "$n1\n"; + if (substr($fileContent,$n1-1,1) eq "<") { + #
    + push @st, $n1; + #print "+".substr($fileContent,$n1,20)."\n"; + $n1=$n1+3; + $pos=$n1; + next; + } + if (substr($fileContent,$n1-1,1) eq "/" && substr($fileContent,$n1-2,1) eq "<") { + #print "-".substr($fileContent,$n1,20)."\n"; + if (scalar @st == 0) { + if ($se eq "dt") { + $n1=index($fileContent,"",$n1); + $n1=$n1+7; + #print "".substr($fileContent,$n3+1,$n1-$n3-length($se)-1); + } + my $r=substr($fileContent,$n3+1,$n1-$n3-length($se)-1); + $section{$id_name}=$r; + #print "$r \n$id_name\n"; + #exit; + $n1=-1; + next; + } + my $nnn=pop @st; + $pos=$n1+length($se); + next; + } + $pos=$n1+length($se); + } + } + $n2=$n2+1; + print ""; + } + $pos=$n2; + } else { $pos=$n1;} + } +#td func +#print "file $file\n"; +$pos=0; + while( $pos > -1) { + #td function + my $ist=index($fileContent,$keys[$lvl],$pos); + if ($ist > -1) { + my $ien=index($fileContent,$keys[$lvl+1],$ist); + if ($ien >-1) { + my $posval=$ist+length($keys[$lvl]); + $val=substr($fileContent,$posval,$ien-$posval); + print "Read file $file .. " if $cc == 0; + parseTag($val); + $pos=$ien+length($keys[$lvl+1]); + $cc++; + } else { + die "Not closed tag TD. File : $file position : $ist\n"; + } + } else { + $pos=$ist; + } + } + +print " Ok.\n" if $cc > 0; + +} + +print " TD count $TDcount\n"; +open(F, '>', "_func.txt") or die $!; +my $c0=0; +foreach my $key (sort keys %useref) { + $function_help{$key}=$section{$key}; + #print "section $key\n"; + $c0++; +} +print "Add section $c0\n"; +foreach my $key (sort keys %function_help) { + #print "$key: $function_help{$key}\n"; + print F "#".$key."\n".$function_help{$key}."\n"; + +} +close(F); +exit; + +sub parseTag +{ +my $s=shift; +$TDcount++; +my $text; +my $tagname; my $attr; my $vv; +my $pos=0; +my $repl; my $pc; +my $pre=0; +my $fn=0; +my $flit=0; +my $fname; +my $fliteral; +my $href; +my @t=(); + while ($pos /g; + if (substr($tagname,0,3) eq "pre") {$pre=0;} + $pos=index($s,'>',$pos)+1; + if (exists $tags{$tagname.$tagnameC}) { + $repl=$tags{$tagname.$tagnameC}; + push @stak, $text, $repl; + } else { + if ($href ne "") { + push @stak, $text, ""; + $useref{$href}=1; + $href=""; + } else { + die "$s\n NOT DEFINE REPALCE CLOSE TAG ${tagname}${tagnameC} pos=$pos\n"; + } + } + if ($tagname eq "codeclass=\"function\"" && $fn == 1 ) { + $fn=0; + $fname=$text; + } + if ($tagname eq "codeclass=\"literal\"" && $flit == 1 ) { + $fliteral=$text; + } + + $text=""; + next; + } + my $tmp=substr($s,$pos); + ($tagname,$attr) = $tmp =~ m/<(\w+)\s*(.*?)>/g; + my $pp=$pos; + $pos=index($s,'>',$pos)+1; + $href=""; + if ($tagname eq "a" ) {($href) = $attr =~ m/href=".*?#(.*?)"/; $attr=""; } + if ($tagname eq "sup" ) {$attr="";} + if ($tagname eq "ul" ) {$attr="";} + if ($tagname eq "pre" ) {$pre=1;} + if ($tagname eq "code" && $attr =~ /literal/ ) {$flit++;} + if ($attr =~ /func_signature/ ) {$fn=1;} + die "$s TAG NAME EMPTY\n" if $tagname eq "" ; + if (exists $tags{$tagname.$attr}) { + $repl=$tags{$tagname.$attr}; + if ($href ne "") { + $repl=""; + $useref{$href}=1; + #print "$repl\n"; + } + push @stak, $text , $repl; + $text=""; + } else { + die "$s\n NOT DEFINE REPALCE OPEN TAG ${tagname}${attr}\n"; + } + #print substr($s,$pos)."\n =============== tag=$tagname, attr=$attr\n"; + push @t, $tagname.$attr; +# print "TAG=${tagname}${attr} pos=$pos prev=$pp\n"; + next; + } else { + my $c=substr($s,$pos,1); + if ($pc eq $c && $c eq " " && $pre == 0) { + + } else { + if ($pre == 1 && $c eq "\n") {$c="
    ";} + $text.=$c; + $pc=$c; + } + } + $pos++; + } + my $rez; +# dump(@stak); + foreach my $t (@stak) { + next if $t eq ""; + $rez.=$t; + } + if (!defined $fname && defined $fliteral) { + $fname=lc($fliteral); + #print "Literal function define $fname\n"; + } + if (defined $fname) { + $fname =~ s/>/>/g; + $fname =~ s/</".$rez; + if ($fname =~ /\||\[/ && length($fname)>3) { + print "Bad name $fname \n"; + } + #print "$s\nAppend REZ: $function_help{$fname}\n"; + } + if (defined $fname && !exists $function_help{$fname}) { + if ($fname =~ /\||\[/ && length($fname)>3) { + print "Bad name $fname \n"; + } + $function_help{$fname}=$rez; + } + +# print "$s\nREZ: $rez\n"; + @stak=(); + +#exit; +} diff --git a/x64/Release_(3.0)/pgAdmin3.exe b/x64/Release_(3.0)/pgAdmin3.exe index 9a93ab2..8ee94d7 100644 Binary files a/x64/Release_(3.0)/pgAdmin3.exe and b/x64/Release_(3.0)/pgAdmin3.exe differ