pgadmin3/utils/dlgTransformText.cpp
lsv 1f3c598d61 Save filter frmGridEditor
При открытии таблицы на редактирование с фильтром, значение заданного
фильтра сохраняется в pgadmin3opt.json.
Мелкие правки dlgTransformText
2024-12-10 09:51:51 +05:00

957 lines
No EOL
29 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pgAdmin3.h"
#include "utils/dlgTransformText.h"
#include "frm/frmMain.h"
#include "ctl/ctlStyledText.h"
#include "utils/sysSettings.h"
#include <wx/log.h>
#include <limits>
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::replace_opt> dlgTransformText::BuildString(const wxString repstr) {
std::vector<replace_opt> 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<dlgTransformText::replace_opt> 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<st.size()) {
auto& j = st[position++];
wxString s;
if (j.isGroup && j.nGroup >= 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 &regfld) {
// 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<replace_opt> repArray;
std::vector<int> 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<replace_opt> 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();
}