#include "pgAdmin3.h" #include "utils/dlgTransformText.h" #include "frm/frmMain.h" #include "ctl/ctlStyledText.h" #include "utils/sysSettings.h" #include #include BEGIN_EVENT_TABLE(dlgTransformText, pgDialog) //EVT_KEY_DOWN(dlgTransformText::OnKeyDown) //EVT_BUTTON(XRCID("btnCancel"), dlgTransformText::OnCancel) EVT_BUTTON(wxID_CANCEL, dlgTransformText::OnCancel) EVT_BUTTON(XRCID("btnOk"), dlgTransformText::OnOk) EVT_BUTTON(XRCID("btnSave"), dlgTransformText::OnSave) EVT_CHECKBOX(XRCID("chkHighLight"), dlgTransformText::OnChangeOnline) //EVT_TEXT(XRCID("LimitCharsText"), dlgTransformText::OnChange) //EVT_TEXT(XRCID("LimitRowsText"), dlgTransformText::OnChange) EVT_COMBOBOX(XRCID("beforeRowCB"), dlgTransformText::OnChange) EVT_COMBOBOX(XRCID("sepFieldCB"), dlgTransformText::OnChange) EVT_COMBOBOX(XRCID("afterRowCB"), dlgTransformText::OnChange) //EVT_COMBOBOX(XRCID("afterFieldCB"), dlgTransformText::OnChange) EVT_COMBOBOX(XRCID("optionsLoadCB"), dlgTransformText::OnLoad) EVT_TEXT(XRCID("beforeRowCB"), dlgTransformText::OnChange) EVT_TEXT(XRCID("sepFieldCB"), dlgTransformText::OnChange) EVT_TEXT(XRCID("afterRowCB"), dlgTransformText::OnChange) //EVT_TEXT(XRCID("afterFieldCB"), dlgTransformText::OnChange) EVT_TEXT(XRCID("LimitRowsText"), dlgTransformText::OnChangeLimit) EVT_TEXT(XRCID("LimitCharsText"), dlgTransformText::OnChangeLimit) //EVT_KILL_FOCUS(dlgTransformText::OnKillFocus) //EVT_STC_MODIFIED(XRCID("RegText"), dlgTransformText::OnChangeRegEx) //EVT_STC_MODIFIED(XRCID("ReplaceText"), dlgTransformText::OnChangeRegEx) EVT_STC_UPDATEUI(XRCID("RegText"), dlgTransformText::OnChangeRegEx2) EVT_STC_UPDATEUI(XRCID("ReplaceText"), dlgTransformText::OnChangeRegEx2) //EVT_COMMAND_KILL_FOCUS(XRCID("RegText"), dlgTransformText::OnKillFocusRegEx) //EVT_TEXT(XRCID("RegText"), dlgTransformText::OnChangeRegEx) EVT_IDLE(dlgTransformText::OnIdle) EVT_CLOSE(dlgTransformText::OnClose) END_EVENT_TABLE() #define btnOK CTRL_BUTTON("wxID_OK") #define btnCancel CTRL_BUTTON("wxID_CANCEL") #define btnSave CTRL_BUTTON("btnSave") #define m_msg CTRL_STATIC("m_msg") //#define afterFieldCB CTRL_COMBOBOX1("afterFieldCB") #define srcText CTRL_STYLEDTEXT("srcText") #define trgText CTRL_STYLEDTEXT("trgText") #define LimitCharsText CTRL_TEXT("LimitCharsText") #define LimitRowsText CTRL_TEXT("LimitRowsText") #define chkHighLight CTRL_CHECKBOX("chkHighLight") #define beforeRowCB CTRL_COMBOBOX1("beforeRowCB") #define afterRowCB CTRL_COMBOBOX1("afterRowCB") #define sepFieldCB CTRL_COMBOBOX1("sepFieldCB") //#define afterFieldCB CTRL_COMBOBOX1("afterFieldCB") #define optionsLoadCB CTRL_COMBOBOX1("optionsLoadCB") #define txtField CTRL_STYLEDTEXT("RegText") #define trgField CTRL_STYLEDTEXT("ReplaceText") dlgTransformText::dlgTransformText(ctlSQLBox* form,const wxString source) : pgDialog() { this->inizialize = true; SetFont(settings->GetSystemFont()); LoadResource(form, wxT("dlgTransformText")); RestorePosition(); SetTitle(_("Transformation text")); LoadOptions(); //srcText->Set //extern sysSettings* settings; SetDecoration(srcText); SetDecoration(trgText); SetDecoration(txtField); SetDecoration(trgField); txtField->setRegExphighlight(true); wxAcceleratorEntry entries[1]; entries[0].Set(wxACCEL_NORMAL, WXK_ESCAPE, wxID_CANCEL); wxAcceleratorTable accel(1, entries); SetAcceleratorTable(accel); //optionsLoadCB->Connect(wxID_ANY, wxEVT_KILL_FOCUS, wxFocusEventHandler(dlgTransformText::OnKillFocus),this); } void dlgTransformText::SetDecoration(ctlStyledText *s) { wxFont fntSQLBox = settings->GetSQLFont(); //srcText->StyleSetForeground(wxSTC_STYLE_DEFAULT, frColor); s->StyleSetFont(wxSTC_STYLE_DEFAULT, fntSQLBox); s->SetSelBackground(true, wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)); s->SetSelForeground(true, wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT)); } dlgTransformText::~dlgTransformText() { SavePosition(); } void dlgTransformText::SetSource(const wxString& src) { // //srcText->SetValue(src); this->src = src; showNumber(srcText, true); showNumber(trgText, true); this->inizialize = false; wxStyledTextEvent ev; strResult = wxEmptyString; strReg = wxEmptyString; //OnChangeRegEx2(ev); isNeedTransform = true; } void dlgTransformText::showNumber(ctlStyledText* text, bool visible) { if (visible) { long int width = text->TextWidth(wxSTC_STYLE_LINENUMBER, wxT(" ") + wxString::Format("%ld", (long int)limitLine) + wxT(" ")); if (width != text->GetMarginWidth(0)) { text->SetMarginWidth(0, width); text->Update(); } text->SetViewWhiteSpace(wxSTC_WS_VISIBLEALWAYS); text->SetViewEOL(true); } else { text->SetMarginWidth(0, 0); text->Update(); } } wxJSONValue dlgTransformText::LoadConfig(const wxString confname) { wxJSONValue conf(wxJSONType::wxJSONTYPE_OBJECT); wxString n; if (confname.IsEmpty()) n = "last"; else n = confname; bool ischange = false; bool t_inizialize = inizialize; inizialize = true; conf = opt["configurations"][n]; bool islastconf=false; if (!conf.IsNull() && lastconf.Size() > 0) islastconf = true; if (!conf.IsNull()) { wxString s; s = conf["beforeRow"].AsString(); if (islastconf && s != lastconf["beforeRow"].AsString()) { s = lastconf["beforeRow"].AsString(); ischange = true; } beforeRowCB->SetValue(s); s = conf["afterRow"].AsString(); if (islastconf && s != lastconf["afterRow"].AsString()) { s = lastconf["afterRow"].AsString(); ischange = true; } afterRowCB->SetValue(s); s = conf["sepField"].AsString(); if (islastconf && s != lastconf["sepField"].AsString()) { s = lastconf["sepField"].AsString(); ischange = true; } sepFieldCB->SetValue(s); s = conf["regexp"].AsString(); if (islastconf && s != lastconf["regexp"].AsString()) { s = lastconf["regexp"].AsString(); ischange = true; } txtField->SetText(s); s = conf["replace"].AsString(); if (islastconf && s != lastconf["replace"].AsString()) { s = lastconf["replace"].AsString(); ischange = true; } trgField->SetText(s); //afterFieldCB->SetValue(conf["fieldSeparator"].AsString()); if (islastconf) { opt["currentConfingName"] = n; } if (ischange) n = '*' + n; optionsLoadCB->SetValue(n); isChange = ischange; lastconf = conf; } inizialize = t_inizialize; return lastconf; } void dlgTransformText::LoadOptions() { wxJSONValue def(wxJSONType::wxJSONTYPE_OBJECT); //wxJSONValue confArray(wxJSONType::wxJSONTYPE_ARRAY); wxJSONValue confs(wxJSONType::wxJSONTYPE_OBJECT); wxJSONValue grpArray(wxJSONType::wxJSONTYPE_ARRAY); opt.SetType(wxJSONType::wxJSONTYPE_OBJECT); lastconf.SetType(wxJSONType::wxJSONTYPE_OBJECT); const wxString clrgroup[] = { "#ffff00" ,"#c4e8ac","#f7d6a6","#c7c7fc","#f1cdfd","#ffc6be" ,"#cae7d6" ,"#c4e7ab" ,"#f4d7a5" ,"#c7c8fe","#f2cffd" ,"#ffc4bd", "#c7e7d4" }; for (int k = 0; k < sizeof(clrgroup) / sizeof(clrgroup[0]); k++) { //wxJSONValue grp(wxJSONType::wxJSONTYPE_OBJECT); //grp["number"] = k; //grp["color"] = clrgroup[k]; grpArray.Append(clrgroup[k]); } def["colorGroup"] = grpArray; def["newLineSeparator"] = wxString("\\r\\n|\\r[^\\n]|\\n"); def["bgErrorColor"] = wxString("#f4dcdc"); wxJSONValue conf(wxJSONType::wxJSONTYPE_OBJECT); //conf["name"] = wxString("last"); wxString name = "last"; //conf["name"] = wxString("last"); def["currentConfingName"] = wxString(""); conf["regexp"] = wxString("\\d+"); conf["replace"] = wxString("\\g{0}"); conf["beforeRow"] = wxString(""); conf["afterRow"] = wxString(""); conf["sepField"] = wxString(","); conf["afterField"] = wxString(""); conf["fieldSeparator"] = wxString(""); confs[name] = conf; def["configurations"] = confs; def["onLineRefresh"] = true; int limline = 50; def["LimitShowLine"] = limline; int limchar = 50000; def["LimitShowChar"] = limchar; settings->ReloadJsonFileIfNeed(); settings->ReadJsonObect(dlgName, opt, def); if (!opt.IsNull()) { wxString strcolor = opt["bgErrorColor"].AsString(); wxColour cc(strcolor); if (!cc.IsOk()) opt["bgErrorColor"] = def["bgErrorColor"]; } else opt = def; bgerror = wxColour(opt["bgErrorColor"].AsString()); lastconf = opt["configurations"][name]; wxArrayString ar = opt["configurations"].GetMemberNames(); for (int i = 0; i < ar.Count(); i++) { wxString s; wxJSONValue cf= opt["configurations"][ar[i]]; wxString s2; if (ar[i] == "last") continue; s2 = cf["beforeRow"].AsString(); beforeRowCB->Append(s2); s2 = cf["afterRow"].AsString(); afterRowCB->Append(s2); s2 = cf["sepField"].AsString(); sepFieldCB->Append(s2); // s2 = cf["afterField"].AsString(); // afterFieldCB->Append(s2); s2 = ar[i]; optionsLoadCB->Append(s2); } wxString s=opt["currentConfingName"].AsString(); if (opt["LimitShowLine"].IsInt()) limline= opt["LimitShowLine"].AsInt(); if (opt["LimitShowChar"].IsInt()) limchar = opt["LimitShowChar"].AsInt(); limitLine = limline; limitChar = limchar; srcRowSep = opt["newLineSeparator"].AsString(); wxRegEx RegNewLine(srcRowSep, wxRE_NEWLINE); if (!RegNewLine.IsValid()) srcRowSep= def["newLineSeparator"].AsString(); LimitRowsText->SetValue(opt["LimitShowLine"].AsString()); LimitCharsText->SetValue(opt["LimitShowChar"].AsString()); isOnline = chkHighLight->IsChecked(); LoadConfig(s); wxCommandEvent ev; OnCheckUI(ev); } int str_to_int(const wxString& s) { int ii = INT_MAX; int scanned = wxSscanf(s, "%d", &ii); return ii; } void dlgTransformText::CheckLimits() { wxString s = LimitRowsText->GetValue(); int l; l = str_to_int(s); if (s.length() == 0|| l==0) { l = INT_MAX; // unlimited } else { if (l == INT_MAX) l = 50; } limitLine = l; s = LimitCharsText->GetValue(); l = str_to_int(s); if (s.length() == 0|| l==0) { l = INT_MAX; // unlimited } else { if (l == INT_MAX) l = 50000; } limitChar = l; } std::vector dlgTransformText::BuildString(const wxString repstr) { std::vector rez; bool isback = false; wxString a; wxString e; for (int i = 0; i < repstr.length(); i++) { wxChar c = repstr[i]; if (c == '\n'|| c=='\r') continue; if (!isback && c == '\\') { isback = true; continue; } if (isback) { if (c == 'r') c = '\r'; else if (c == 'n') c = '\n'; else if (c == 't') c = '\t'; else if (c == 'g'|| c=='G') { int l = repstr.length(); if (l - i > 2) { int pos = repstr.find_first_of('}', i); int flags = 0; if (pos >= 0) { wxString ngrp = repstr.substr(i + 2, pos - i - 2); int ngroup = -1; int scanned = wxSscanf(ngrp, "%d", &ngroup); if (scanned == 1) { if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a }); a.clear(); if (c == 'G') flags |= 1; rez.push_back({ true,ngroup,wxEmptyString,flags,i-1,pos-i+2 }); i = pos; isback = false; continue; } } } e = wxString::Format("\\g{n} incorrect in pos %d", i); } isback = false; } else if (c == '[') { if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a }); a.clear(); rez.push_back({ true,(int)eTypeGroup::USER_GROUP_START,wxEmptyString }); continue; } else if (c == ']') { if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a }); a.clear(); rez.push_back({ true,(int)eTypeGroup::USER_GROUP_END,wxEmptyString }); continue; } a.Append(c); if (e.length() > 0) break; } if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a }); return rez; } void dlgTransformText::AppendTextControl(ctlStyledText* ctrl, const wxString appendtext, bool isnewline) { bool isLimit = limitLine <= 0 || limitChar <= 0; if (ctrl == srcText) { // control limit if (isnewline) if (limitLine > 0) limitLine--; else isLimit = true; if (limitChar > 0) limitChar -= appendtext.length(); else isLimit = true; if (!isLimit) ctrl->AppendText(appendtext); } else { strResult.Append(appendtext); ctrl->AppendText(appendtext); } } wxJSONValue dlgTransformText::FillConfig() { wxString s; wxJSONValue n(wxJSONType::wxJSONTYPE_OBJECT); s=beforeRowCB->GetValue(); n["beforeRow"]=s; s = afterRowCB->GetValue(); n["afterRow"] = s; s = sepFieldCB->GetValue(); n["sepField"] = s; // s= afterFieldCB->GetValue(); // n["afterField"] = s; // s=beforeFieldCB->GetValue(); // n["beforeField"] = s; s= txtField->GetText(); n["regexp"] = s; s= trgField->GetText(); n["replace"] = s; return n; }; void dlgTransformText::OnChange(wxCommandEvent& ev) { OnComboSelect(ev); isNeedTransform = true; } void dlgTransformText::OnChangeLimit(wxCommandEvent& ev) { CheckLimits(); isNeedTransform = true; } void dlgTransformText::OnChangeOnline(wxCommandEvent& ev) { isOnline = chkHighLight->IsChecked(); } void dlgTransformText::OnLoad(wxCommandEvent& ev) { wxString s = optionsLoadCB->GetValue(); //lastconf.Clear(); for (auto key: lastconf.GetMemberNames()) lastconf.Remove(key); LoadConfig(s); OnCheckUI(ev); } void dlgTransformText::OnComboSelect(wxCommandEvent& ev) { //compare lastconf if (inizialize) return; wxJSONValue formconf = FillConfig(); wxArrayString ar; ar=formconf.GetMemberNames(); isChange = false; for (auto s:ar) { wxString ls = lastconf[s].AsString(); wxString form = formconf[s].AsString(); if (form == ls) continue; isChange = true; // if (s == "regexp") { } break; } wxString s = optionsLoadCB->GetValue(); bool isSimbol = s.length() > 1 && s.Mid(0, 1) == '*'; wxString name; if (isSimbol) name = s.Mid(1); else name = s; if (optionsLoadCB->FindString(name) < 0) { isChange = false; // new config } if (isChange && !isSimbol) { //wxString s = optionsLoadCB->GetValue(); if (!isSimbol) { s = '*' + name; optionsLoadCB->SetValue(s); } } if (!isChange && isSimbol && ev.GetEventObject() != optionsLoadCB) optionsLoadCB->SetValue(name); OnCheckUI(ev); } void dlgTransformText::OnSave(wxCommandEvent& ev) { wxString s= optionsLoadCB->GetValue(); if (s.length() > 1 && s.Mid(0, 1) == '*') { s = s.Mid(1); } else { if (optionsLoadCB->FindString(s)<0) optionsLoadCB->Append(s); } opt["currentConfingName"] = s; wxJSONValue formconf = FillConfig(); lastconf = formconf; opt["configurations"][s] = formconf; opt["configurations"]["last"] = formconf; settings->WriteJsonObect(dlgName, opt); settings->WriteJsonFile(); isChange = false; optionsLoadCB->SetValue(s); OnCheckUI(ev); } void dlgTransformText::OnCheckUI(wxCommandEvent& ev) { wxString s = optionsLoadCB->GetValue(); bool issave = false; if (s.length() > 1 && s.Mid(0, 1) == '*') issave = true; if (s.length() > 0 && s.Mid(0, 1) != '*') { if (optionsLoadCB->FindString(s) < 0) issave = true;; } btnSave->Enable(issave && isChange); bool iscopy = strResult.length() > 0; if (strResult.length()>0) btnSave->Enable(iscopy); } void dlgTransformText::OnIdle(wxIdleEvent& ev) { if (inizialize) return; if (!isOnline) return; // int u = ev.GetUpdated(); // if (!(u & wxSTC_UPDATE_CONTENT)) return; wxRegEx regfld; wxString v = txtField->GetText(); wxString r = trgField->GetText(); if (v.length() == 0 || src.length() == 0 || r.length() == 0) return; if (!isNeedTransform) return; wxCommandEvent evt; strResult = wxEmptyString; bool fieldexp = false; //if (v == strReg && strRep == r) return; { wxLogNull logNo; fieldexp = regfld.Compile(v, wxRE_NEWLINE); if (!fieldexp) { if (trgText->GetTextLength() > 0) toplineTrg = trgText->GetFirstVisibleLine(); trgText->ClearAll(); m_msg->SetLabelText(wxString::Format("Error regexp compile!!!")); } } if (fieldexp) { //txtField->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); //txtField->StyleSetBackground(wxSTC_STYLE_DEFAULT, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); } else { //txtField->SetBackgroundColour(bgerror); //txtField->StyleSetBackground(wxSTC_STYLE_DEFAULT, bgerror); //srcText->ClearAll(); //int ls = srcText->GetText().length(); //if ((ls> limitChar )ls!=src.length()) //srcText->SetText(src.Mid(0, limitChar)); srcText->ClearDocumentStyle(); } //txtField->Update(); if (fieldexp) { TransformText(regfld); strRep = r; strReg = v; OnComboSelect(evt); } else { strReg = ""; strRep = ""; } OnCheckUI(evt); isNeedTransform = false; ev.Skip(); } void dlgTransformText::OnChangeRegEx2(wxStyledTextEvent& ev) { int u = ev.GetUpdated(); if ((u & wxSTC_UPDATE_CONTENT)) isNeedTransform = true; } void dlgTransformText::OnClose(wxCloseEvent& ev) { this->Hide(); if (ev.CanVeto()) ev.Veto(); } void dlgTransformText::OnCancel(wxCommandEvent& ev) { //SaveSettings(); this->Hide(); } void dlgTransformText::OnOk(wxCommandEvent& ev) { wxCloseEvent event; if (strResult.length() > 0) { //pgDialog::OnClose(event); if (wxTheClipboard->Open()) { wxDataObjectComposite* dataobj = new wxDataObjectComposite(); dataobj->Add(new wxTextDataObject(strResult)); wxTheClipboard->SetData(dataobj); wxTheClipboard->Close(); } } this->Hide(); } void dlgTransformText::SetStyled(ctlStyledText* s) { int regstyle = wxSTC_STYLE_LASTPREDEFINED + 1; s->StyleClearAll(); s->ClearDocumentStyle(); countGroupColor = opt["colorGroup"].Size(); for (int i = regstyle; i < regstyle + countGroupColor; i++) { wxString strcl = opt["colorGroup"][i - regstyle].AsString(); wxColour clr(strcl); if (clr.IsOk()) { s->StyleSetBackground(i, clr); } else { s->StyleSetBackground(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); } s->StyleSetForeground(i, *wxBLACK); } } wxString dlgTransformText::ReplaceFormatting( const wxString &src, const wxRegEx &r, const std::vector st, int &position, interval m2[], int maxsizeintervalarray, int &currindex, size_t &start_frame) { bool isEmptyGroup = true; int maxgroup = r.GetMatchCount(); wxString replstr; int ci=currindex; size_t sf = start_frame; while (position= 0 && j.nGroup < maxgroup) { s = r.GetMatch(src, j.nGroup); if (ci >= maxsizeintervalarray) break; if (s.length() > 0) isEmptyGroup = false; // verify flags if (j.flags & 1) { // no print group s = wxEmptyString; } m2[ci++] = { sf ,s.length(),j.nGroup }; replstr.Append(s); } else if (j.nGroup == (int)eTypeGroup::SIMPLE_TEXT) { s = j.text; replstr.Append(s); } else if (j.nGroup == (int)eTypeGroup::USER_GROUP_START) { s = ReplaceFormatting(src, r, st, position, m2, 100, ci, sf); if (s.length() > 0) { isEmptyGroup = false; } replstr.Append(s); continue; } else if (j.nGroup == (int)eTypeGroup::USER_GROUP_END) { break; } sf += s.length(); } if (isEmptyGroup) { return wxEmptyString; } else { // OK. save current posintion currindex = ci; start_frame = sf; return replstr; } } void dlgTransformText::TransformText(const wxRegEx ®fld) { // Check params interval m[100]; wxRegEx RegNewLine(srcRowSep, wxRE_NEWLINE); if (trgText->GetTextLength()>0) toplineTrg=trgText->GetFirstVisibleLine(); if (srcText->GetTextLength()>0) toplineSrc = srcText->GetFirstVisibleLine(); srcText->StyleClearAll(); //srcText->SetText(src); srcText->ClearAll(); trgText->StyleClearAll(); trgText->ClearAll(); strResult = wxEmptyString; wxString c = opt["bgErrorColor"].AsString(); wxColour red(c); //c = opt["colorGroup"][0].AsString(); wxColour sel("#ffff00"); int regstyle = wxSTC_STYLE_LASTPREDEFINED + 1; SetStyled(srcText); SetStyled(trgText); SetStyled(trgField); //bool fieldexp = regfld.Compile(v, wxRE_NEWLINE); if (regfld.IsValid()) { int sstart = 0; //int s_indicHighlight = 20; //srcText->IndicatorSetForeground(s_indicHighlight, wxColour(80, 236, 120)); //srcText->IndicatorSetForeground(s_indicHighlight, *wxBLUE); //srcText->IndicatorSetStyle(s_indicHighlight, wxSTC_INDIC_DASH); wxString tmp = src; int numLine = 0; bool isnewline = false; // wxString sepRows = txtSepRows->GetValue(); // wxString sepField = txtSepField->GetValue(); wxString trgFieldReg = trgField->GetText(); std::vector repArray; std::vector colorizetrgField(countGroupColor,-1); repArray = BuildString(trgFieldReg); if (repArray.size() == 0) { trgField->SetBackgroundColour(red); } else { trgField->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); } wxString sepRbegin, sepRend, sepF; sepRbegin=beforeRowCB->GetValue(); sepRend= afterRowCB->GetValue(); sepF = sepFieldCB->GetValue(); //sepFend = afterFieldCB->GetValue(); // build Rows separator std::vector sepRowEndArray; sepRowEndArray = BuildString(sepRend); if (sepRowEndArray.size() == 0) { afterRowCB->SetBackgroundColour(red); } else { afterRowCB->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); } bool isSepRowEndConst = true; wxString SepRowEndConst; for (auto& j : sepRowEndArray) { if (j.isGroup && j.nGroup>=0) { isSepRowEndConst = false; break; } else { SepRowEndConst.Append(j.text); } } // Matchs regexpp wxString sepLine = ""; int numField = 0; int cntMathes = 0; int cntLines = 0; int tmp_limitChar = limitChar; int tmp_limitLine = limitLine; while (regfld.Matches(tmp)) { size_t start, len; int lastBytePosition = srcText->GetLastPosition(); int lastCharPosition = srcText->GetTextLength(); regfld.GetMatch(&start, &len, 0); if (len == 0) break; cntMathes++; wxString no_match = tmp.Mid(0, start); int maxgroup = regfld.GetMatchCount(); // build sepLine string dynamic for next line sepRend = wxEmptyString; if (isSepRowEndConst) { sepRend = SepRowEndConst; } else for (auto& j : sepRowEndArray) { if (j.isGroup && j.nGroup >= 0) { if (j.nGroup >= 0 && j.nGroup < maxgroup) { wxString s = regfld.GetMatch(tmp, j.nGroup); sepRend.Append(s); } } else { sepRend.Append(j.text); } } // end build if (no_match.length() > 0) { isnewline = RegNewLine.Matches(no_match); //srcText->AddText(no_match); AppendTextControl(srcText, no_match, isnewline); if (isnewline) AppendTextControl(trgText, sepRend + sepLine); if (isnewline) cntLines++; } wxString fnd = tmp.Mid(start, len); if (isnewline) { //trgText->AddText(sepRbegin ); AppendTextControl(trgText, sepRbegin); numLine++; numField = 0; isnewline = false; } else { if (numField > 0) AppendTextControl(trgText, sepF); } if (numLine == 0 && numField == 0) AppendTextControl(trgText, sepRbegin); //srcText->AddText(fnd); AppendTextControl(srcText, fnd); numField++; if (maxgroup > 0) { // colorer groups size_t start1, len1; size_t start_frame = start; int currentIdx = 0; for (int i = 0; i < maxgroup; i++) { regfld.GetMatch(&start1, &len1, i); if (i == 0) m[currentIdx++] = { start1, len1,0 + regstyle }; if (i == 0 || len1 == 0) continue; // group color // разделение отрезков int maxSizeArray = sizeof(m) / sizeof(m[0]); bool isApeendInterval = false; int shiftcount = 0; for (int idx = 0; idx < currentIdx; idx++) { interval ii = m[idx]; int nextinterval = ii.start + ii.len; if (nextinterval < start1 || ii.len == 0) continue; // предудущие интервалы //nextinterval < start1 + len1 && if (nextinterval < start1 + len1) { if (currentIdx - 1 != idx) continue; // только в конеч добавляем. //следующие интеравлы, добавим сюда наш новый интервал shiftcount = 1; isApeendInterval = true; if (currentIdx + shiftcount >= maxSizeArray) { // переполнение массива break; } if (shiftcount > 0) for (int j = currentIdx - 1; j > idx; j--) m[j + shiftcount] = m[j]; m[idx + 1] = { start1,len1,i + regstyle }; break; } // попали в текущий интервал, разделим его // сдвинем элементы на два,один или ноль вправо shiftcount = 2; int oldleftidx = idx; int oldrightidx = idx + 2; int newcenter = idx + 1; if (start1 == ii.start) { shiftcount--; oldleftidx = -1; newcenter = idx; oldrightidx--; }; // левая часть полностью замещается, стыковака к левой границе if (nextinterval == start1 + len1) { oldrightidx = -1; newcenter = idx + 1; shiftcount--; // правая часть не нужна стыкова к правой границе // сдвиг на shiftcount элементов if (shiftcount == 0) newcenter = idx; } if (currentIdx + shiftcount >= maxSizeArray) { // переполнение массива isApeendInterval = true; break; } if (shiftcount > 0) for (int j = currentIdx - 1; j > idx; j--) m[j + shiftcount] = m[j]; currentIdx += shiftcount; if (oldleftidx != -1) m[idx].len = start1 - ii.start; // правая часть старого интеравла корректируется по длине m[newcenter] = { start1,len1,i + regstyle }; // новый интервал в конец массива if (oldrightidx != -1) m[oldrightidx] = { start1 + len1,ii.len - (start1 - ii.start) - len1 ,ii.style }; // вторая часть старого интервала в конец массива isApeendInterval = true; break; } if (!isApeendInterval) m[currentIdx++] = { start1,len1,i + regstyle }; } // set style for text int maxchar = srcText->GetTextLength(); for (auto& ii : m) { if (--currentIdx < 0) break; if (sstart + ii.start + ii.len > maxchar) break; int CharPos = srcText->PositionRelative(0, sstart+ii.start); if (CharPos == 0 && sstart>1000) { //wxTrap(); continue; } srcText->StartStyling(CharPos); if (ii.style - regstyle > countGroupColor) ii.style = countGroupColor + regstyle - 1; int CharPosEnd = srcText->PositionRelative(CharPos, ii.len); srcText->SetStyling(CharPosEnd - CharPos, ii.style); } // build replace string interval m2[100]; currentIdx = 0; start_frame = 0; int pos = 0; wxString replstr = ReplaceFormatting(tmp, regfld,repArray, pos, m2, 100, currentIdx, start_frame); //trgText->AddText(replstr); //AppendTextControl(trgText, ); int start2 = trgText->GetTextLength(); AppendTextControl(trgText, replstr); maxchar = trgText->GetTextLength(); for (auto& ii : m2) { if (--currentIdx < 0) break; if (start2 + ii.start + ii.len > maxchar) break; int CharPos = trgText->PositionRelative(start2, ii.start); if (CharPos < start2 ) { //wxTrap(); continue; } trgText->StartStyling(CharPos); if (ii.style >= countGroupColor) ii.style = countGroupColor - 1; int CharPosEnd = trgText->PositionRelative(CharPos, ii.len); trgText->SetStyling(CharPosEnd - CharPos, ii.style + regstyle); // colorize wxString trgFieldReg = trgField->GetText(); if (ii.style < colorizetrgField.size() && colorizetrgField[ii.style]==-1) { colorizetrgField[ii.style] = ii.style; } } } else { AppendTextControl(trgText, fnd); } //if (sstart == -1) sstart = 0; sstart += start + len; tmp = tmp.Mid(start + len); } if (numField > 0) AppendTextControl(trgText, sepRend); if (sstart == 0) { srcText->SetText(src.Mid(0, limitChar)); } else if (tmp.length() > 0 && limitChar>0 ) AppendTextControl(srcText, tmp.Mid(0, limitChar)); // no_match limitChar = tmp_limitChar; limitLine = tmp_limitLine; int srcl = src.length(); m_msg->SetLabelText(wxString::Format("Lines %d Char %d Matches %d", cntLines, srcl, cntMathes)); // colorize wxString trgFieldReg = trgField->GetText(); int pp = -1; for (auto &stl: colorizetrgField) { if (stl == -1) continue; for (auto& j : repArray) { if (j.isGroup && j.nGroup >= 0 && stl== j.nGroup) { int CharPos = trgField->PositionRelative(0, j.start); trgField->StartStyling(CharPos); int CharPosEnd = trgField->PositionRelative(CharPos, j.len); trgField->SetStyling(CharPosEnd - CharPos, stl + regstyle); } } } } else { //txtField->SetBackgroundColour(red); srcText->SetText(src.Mid(0, limitChar)); } if (srcText->GetTextLength()>= limitChar) srcText->AppendText("\n..."); if (srcText->GetTextLength() > 0) srcText->SetFirstVisibleLine(toplineSrc); if (trgText->GetTextLength() > 0) trgText->SetFirstVisibleLine(toplineTrg); srcText->Update(); txtField->Refresh(); trgField->Update(); }