diff --git a/LookDBF.vcxproj b/LookDBF.vcxproj index 02140e6..9ab0225 100644 --- a/LookDBF.vcxproj +++ b/LookDBF.vcxproj @@ -89,6 +89,7 @@ MultiThreadedDebugDLL false false + true src\LookDBF.def @@ -107,6 +108,7 @@ MultiThreadedDebugDLL false false + true src\LookDBF.def @@ -178,12 +180,20 @@ + + + + + + + + + PreserveNewest Document - PreserveNewest Document diff --git a/LookDBF.vcxproj.filters b/LookDBF.vcxproj.filters index fa6e351..efbe0ba 100644 --- a/LookDBF.vcxproj.filters +++ b/LookDBF.vcxproj.filters @@ -70,6 +70,12 @@ Source Files + + + + + + diff --git a/file_id.diz b/file_id.diz index 59c8f28..699ace9 100644 --- a/file_id.diz +++ b/file_id.diz @@ -1,4 +1,4 @@ - LookDBF version 2.7. 25.03.2016 + LookDBF version 2.8. 21.07.2016 Plug-In for Far Manager 1.75 and higher --------------------------------------- @@ -11,11 +11,12 @@ Written by: Alexei Boltunov. alexbolt@mail.ru alexbolt@narod.ru -Updated by Andrew Nefedkin. +Maintained by Andrew Nefedkin. https://github.com/Vertigo093i/Far-LookDBF +Special thanks to Aleksander Buniak. - LookDBF ўҐабЁп 2.7. 25.03.2016 + LookDBF ўҐабЁп 2.8. 21.07.2016 Џ« ЈЁ­ ¤«п Far 1.75 Ё ўлиҐ --------------------------------------- ‘ Ёб室­л¬Ё ⥪бв ¬Ё ¤«п MSVC++ @@ -27,6 +28,6 @@ DBF-д © Ђ«ҐЄбҐ© Ѓ®«вг­®ў. E-mail: alexbolt@mail.ru Ё«Ё alexbolt@narod.ru http://alexbolt.narod.ru -„®а Ў®вЄ : Ђ­¤аҐ© ЌҐдс¤ЄЁ­. +„®а Ў®вЄ  Ё Ї®¤¤Ґа¦Є : Ђ­¤аҐ© ЌҐдс¤ЄЁ­. https://github.com/Vertigo093i/Far-LookDBF - +Ћв¤Ґ«м­®Ґ бЇ бЁЎ®: Aleksander Buniak. diff --git a/src/LookDBF.cpp b/src/LookDBF.cpp index f9b79e2..b6b9927 100644 --- a/src/LookDBF.cpp +++ b/src/LookDBF.cpp @@ -114,7 +114,7 @@ bool LOOK::YesAlphaNum(BYTE c) } //=========================================================================== -void LOOK::ToOem(TCHAR *src, TCHAR *dst) +void LOOK::ToOem(char *src, char *dst) { if (!dst) dst = src; if (!ChaTa) { CharToOem(src, dst); return; } @@ -123,7 +123,7 @@ void LOOK::ToOem(TCHAR *src, TCHAR *dst) } //=========================================================================== -void LOOK::ToAlt(TCHAR *src, TCHAR *dst) +void LOOK::ToAlt(char *src, char *dst) { if (!dst) dst = src; if (!ChaTa) { OemToChar(src, dst); return; } @@ -188,9 +188,10 @@ void LOOK::ShowMemo(short id) else { y1 = 0; y2--; } char title[64], nafi[32]; if (Yes(WinCode)) ToOem(coCurr->name, nafi); + else lstrcpy(nafi, coCurr->name); FSF.sprintf(title, "%sД%luД%lu", nafi, recV[curY], nb); if (id) Info.Editor(fname, title, 0, y1, -1, y2, - VF_DISABLEHISTORY | VF_DELETEONLYFILEONCLOSE, 0, 1); + EF_DISABLEHISTORY | EF_DELETEONLYFILEONCLOSE, 0, 1); else Info.Viewer(fname, title, 0, y1, -1, y2, VF_DISABLEHISTORY | VF_DELETEONLYFILEONCLOSE); } @@ -293,14 +294,15 @@ void LOOK::ShowExpMsg(DWORD msec) void LOOK::InitColumns(void) { - WORD i, n; C[0].Clear(); - for (i = 0; i < db.nfil; i++) { + FSF.itoa(db.dbH.nrec, C[0].name, 10); + short maxWidth = sw - (Yes(LineNums) ? lstrlen(C[0].name) + 1 : 0) - 2; + for (WORD i = 0; i < db.nfil; i++) { db.FiNum(i); C[i].finum = i; lstrcpy(C[i].name, db.cf->name); C[i].wid = db.FiWidth() + 1; - n = lstrlen(C[i].name) + 2; if (C[i].wid < n) C[i].wid = n; - n = sw - 3; if (C[i].wid > n)C[i].wid = n; + short n = lstrlen(C[i].name) + 2; if (C[i].wid < n) C[i].wid = n; + if (C[i].wid > maxWidth) C[i].wid = maxWidth; if (i)C[i - 1].After(C + i); } Hid = coLast = NULL; coCurr = coFirst = C; @@ -759,6 +761,7 @@ void LOOK::EditHeader(void) ++i; //2 di[i].Type = DI_FIXEDIT; di[i].X1 = 36; di[i].X2 = 37; di[i].Y1 = 2; FSF.sprintf(di[i].Data, "%02X", db.dbH.type); di[i].Focus = true; + di[i].Flags = DIF_MASKEDIT; di[i].Mask = "HH"; ++i; //3 di[i].Type = DI_TEXT; di[i].X1 = 6; di[i].Y1 = 3; lstrcpy(di[i].Data, GetMsg(mLastUpdate)); @@ -772,6 +775,7 @@ void LOOK::EditHeader(void) ++i; //6 di[i].Type = DI_FIXEDIT; di[i].X1 = 36; di[i].X2 = 37; di[i].Y1 = 4; FSF.sprintf(di[i].Data, "%02X", db.dbH.ind); + di[i].Flags = DIF_MASKEDIT; di[i].Mask = "HH"; ++i; //7 di[i].Type = DI_TEXT; di[i].Y1 = 5; di[i].Flags = DIF_SEPARATOR; ++i; //8 @@ -827,8 +831,20 @@ WORD LOOK::EditField(BYTE nll) if (db.cf->type == 'G' || db.cf->type == 'P' || db.cf->type == 'M' || db.cf->type == '0') return 1; db.fmtD = fmtD; db.fmtT = fmtT; - db.FiDispE(di[0].Data); - if (Yes(WinCode) && db.FiChar())ToOem(di[0].Data); + WORD w = db.FiWidth(); + if (w < 512) // sizeof(FarDialogItem::Data) + { + db.FiDispE(di[0].Data); + if (Yes(WinCode) && db.FiChar()) ToOem(di[0].Data); + } + else + { + di[0].Flags |= DIF_VAREDIT; + di[0].Ptr.PtrLength = w + 1; + di[0].Ptr.PtrData = new char[di[0].Ptr.PtrLength]; + db.FiDispE(di[0].Ptr.PtrData); + if (Yes(WinCode) && db.FiChar()) ToOem(di[0].Ptr.PtrData); + } switch (db.cf->type) { case 'T': di[0].Type = DI_FIXEDIT; di[0].Mask = T_Mask; di[0].Flags = DIF_MASKEDIT; break; @@ -843,8 +859,10 @@ WORD LOOK::EditField(BYTE nll) DiField, 0) < 0) { db.fmtD = fmtDV; db.fmtT = fmtTV; return 1; } - if (Yes(WinCode) && db.FiChar())ToAlt(di[0].Data); - db.SetField(di[0].Data); + auto r = (di[0].Flags & DIF_VAREDIT) != 0 && di[0].Ptr.PtrData ? di[0].Ptr.PtrData : di[0].Data; + if (Yes(WinCode) && db.FiChar()) ToAlt(r); + db.SetField(r); + if ((di[0].Flags & DIF_VAREDIT) != 0 && di[0].Ptr.PtrData) delete di[0].Ptr.PtrData; db.fmtD = fmtDV; db.fmtT = fmtTV; REFRESH: if (db.ReWrite()) { ShowError(2); return 1; } @@ -961,7 +979,7 @@ void LOOK::ShowCur(void) void LOOK::ShowPage(void) { - char s[512]; + char s[MAX_DBFIELD_LENGTH]; WORD i, j, x; DWORD rn; Column *c; @@ -1464,8 +1482,8 @@ void LOOK::FieldValue(WORD fnum, CondValue *val) } break; default: - BYTE_COPY: CopyMemory(b, c, db.cf->filen); - b[db.cf->filen] = 0; + BYTE_COPY: CopyMemory(b, c, db.cf->cfilen); + b[db.cf->cfilen] = 0; } if (db.cf->type == 'N' || db.cf->type == 'F')val->i64 = a_i64((char *) b, 0, db.cf->dec); } @@ -1498,7 +1516,7 @@ short LOOK::FieldCompare(short fnum, CondValue *v1, CondValue *v2) return 2; BYTE_CMP: default: - for (i = 0; ifilen; i++) { + for (i = 0; icfilen; i++) { if (v1->bt[i] > v2->bt[i]) return 0; if (v1->bt[i] < v2->bt[i]) return 1; } @@ -1509,17 +1527,14 @@ short LOOK::FieldCompare(short fnum, CondValue *v1, CondValue *v2) WORD LOOK::ExpTxt(void) { - char s[384], r[512]; - HANDLE ef; - Column *c; + char s[MAX_DBFIELD_LENGTH], r[MAX_DBFIELD_LENGTH]; short w, k; - BYTE sep; lstrcpy(s, Exp.File); lstrcat(s, ".txt"); - ef = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + HANDLE ef = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (ef == INVALID_HANDLE_VALUE) { ShowError(21); return 1; } - sep = Yes(ExpSeparator); s[0] = Exp.Sep[0]; s[1] = Exp.Sep[1]; s[2] = 0; + BYTE sep = Yes(ExpSeparator); + s[0] = Exp.Sep[0]; s[1] = Exp.Sep[1]; s[2] = 0; db.fmtD = fmtDE; db.fmtT = fmtTE; if (sep) { if (s[0]) { @@ -1530,7 +1545,7 @@ WORD LOOK::ExpTxt(void) } if (sep == 0xb3 && (Exp.code == 1 || (Exp.code == 0 && Yes(WinCode)))) sep = 0xa6; if (Yes(ExpHeads)) { - for (c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { + for (auto c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { lstrcpy(s, c->name); w = c->wid - 1; k = w; db.FiNum(c->finum); if (db.cf->type == 'D') k = DTw(db.fmtD); if (db.cf->type == 'T') k = DTw(db.fmtT); if (k > w) w = k; @@ -1545,7 +1560,7 @@ WORD LOOK::ExpTxt(void) } if (Yes(ExpEmpty)) goto FINISH; while ((this->*ExpRec)()) { - for (c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { + for (auto c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { db.FiNum(c->finum); k = db.FiDisp(s); w = c->wid - 1; if (db.FiChar()) { if (Exp.code == 1)ToAlt(s); else if (Exp.code == 2) ToOem(s); @@ -1578,14 +1593,11 @@ WORD LOOK::ExpTxt(void) WORD LOOK::ExpHtm(void) { - char s[384], r[512]; - HANDLE ef; - Column *c; + char s[MAX_DBFIELD_LENGTH], r[MAX_DBFIELD_LENGTH]; const char *rs, *rf, *cs, *cf, *fi, *fs, *fsn, *fss; lstrcpy(s, Exp.File); lstrcat(s, ".htm"); - ef = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + HANDLE ef = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (ef == INVALID_HANDLE_VALUE) { ShowError(21); return 1; } db.fmtD = fmtDE; db.fmtT = fmtTE; rs = GetMsg(mTabRowS); rf = GetMsg(mTabRowF); @@ -1596,7 +1608,7 @@ WORD LOOK::ExpHtm(void) if (Yes(ExpHeads)) { FSF.sprintf(r, fs, rs); if (MyWrite(ef, r)) goto BAD_WRITE; - for (c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { + for (auto c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { if (!c->name[0]) FSF.sprintf(r, fss, cs, fi, cf); else { lstrcpy(s, c->name); FSF.Trim(s); @@ -1613,7 +1625,7 @@ WORD LOOK::ExpHtm(void) while ((this->*ExpRec)()) { FSF.sprintf(r, fs, rs); if (MyWrite(ef, r)) goto BAD_WRITE; - for (c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { + for (auto c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { db.FiNum(c->finum); db.FiDisp(s); FSF.Trim(s); if (!s[0]) FSF.sprintf(r, fss, cs, fi, cf); else { @@ -1644,22 +1656,19 @@ WORD LOOK::ExpHtm(void) WORD LOOK::ExpDbf(void) { - char s[384]; - Column *c; + char s[MAX_PATH]; dbBase a; - WORD n; - BYTE sep, nn; - sep = db.dbH.type; s[0] = Exp.Type[0]; s[1] = Exp.Type[1]; s[2] = 0; + BYTE sep = db.dbH.type; s[0] = Exp.Type[0]; s[1] = Exp.Type[1]; s[2] = 0; if (Yes(ExpFileType) && s[0] && s[1]) sep = ah_i64(s, sep); - for (c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { + for (auto c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { db.FiNum(c->finum); if ((db.cf->spare[0] & 0x05) == 5 && db.cf->type == '0') continue; lstrcpy(s, c->name); s[10] = 0; if (Exp.code == 1)ToAlt(s); else if (Exp.code == 2) ToOem(s); a.AddF(db.cf, s); } - nn = a.AddNull(); + BYTE nn = a.AddNull(); CopyMemory(a.dbH.spare1, db.dbH.spare1, 20); lstrcpy(s, Exp.File); lstrcat(s, ".dbf"); if (a.Create(s, sep)) { ShowError(1); return 1; } @@ -1667,15 +1676,18 @@ WORD LOOK::ExpDbf(void) while ((this->*ExpRec)()) { a.rec[0] = db.rec[0]; if (a.Nflg && nn) ZeroMemory(a.Nflg, nn); + WORD n; + Column *c; + BYTE b[MAX_DBFIELD_LENGTH]; for (n = 0, c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { db.FiNum(c->finum); if ((db.cf->spare[0] & 0x05) == 5 && db.cf->type == '0') continue; - a.FiNum(n); ++n; db.GetByte((BYTE*) s); + a.FiNum(n); ++n; db.GetByte(b); if (db.FiChar()) { - if (Exp.code == 1)ToAlt(s); - else if (Exp.code == 2) ToOem(s); + if (Exp.code == 1)ToAlt((char *) b); + else if (Exp.code == 2) ToOem((char *) b); } - a.SetByte((BYTE*) s); + a.SetByte(b); if (db.FiNull())a.SetNull(); if (db.FiNotFull())a.SetNotFull(); } @@ -1811,7 +1823,7 @@ WORD LOOK::Import(void) if (!db.cf->spare[13]) continue; a.FiNum(db.cf->spare[13] - 1); ar = a.rec + a.cf->loc; br = db.rec + db.cf->loc; - for (k = 0; k < a.cf->filen; k++)br[k] = ar[k]; + for (k = 0; k < a.cf->cfilen; k++)br[k] = ar[k]; } db.Write(); if (a.NextRec()) break; @@ -2105,7 +2117,7 @@ void LOOK::CondVal(WORD n) default: if (Yes(WinCode) && db.FiChar())ToAlt(s, b); else lstrcpy(b, s); - b[db.cf->filen] = 0; + b[db.cf->cfilen] = 0; } } //=========================================================================== @@ -2260,30 +2272,29 @@ bool LOOK::CondCheck(short n, DWORD fi1, DWORD fi2) bool LOOK::CondCompare(short n) { - BYTE *s, b[256]; - short i; db.FiNum(Cond.Field[n]); - s = db.rec + db.cf->loc; + auto s = db.rec + db.cf->loc; switch (db.cf->type) { case 'T': // DateTime if (db.cf->filen == 8) { // Binary format union { DWORD w; BYTE c[4]; } u, v; - for (i = 0; i < 4; i++)u.c[i] = s[i]; - for (i = 4; i < 8; i++)v.c[i - 4] = s[i]; + for (BYTE i = 0; i < 4; i++) u.c[i] = s[i]; + for (BYTE i = 4; i < 8; i++) v.c[i - 4] = s[i]; return CondCheck(n, u.w, v.w); } break; case 'Y': // Currency union { __int64 w; BYTE c[8]; } cy; - for (i = 0; i < 8; i++)cy.c[i] = s[i]; + for (BYTE i = 0; i < 8; i++) cy.c[i] = s[i]; return CondCheck(n, cy.w); case 'N': case 'F': // Number, Float - for (i = 0; i < db.cf->filen; i++)b[i] = s[i]; + BYTE b[256]; + CopyMemory(b, s, db.cf->filen); b[db.cf->filen] = 0; return CondCheck(n, a_i64((char *) b, 0, db.cf->dec)); case 'B': // Double union { double w; BYTE c[8]; } uu; - for (i = 0; i < 8; i++)uu.c[i] = s[i]; + for (BYTE i = 0; i < 8; i++) uu.c[i] = s[i]; return CondCheck(n, uu.w); case '0': // System case 'G': // General @@ -2292,10 +2303,11 @@ bool LOOK::CondCompare(short n) return false; case 'I': // Integer union { __int32 w; BYTE c[4]; } uuu; - for (i = 0; i < 4; i++)uuu.c[i] = s[i]; + for (BYTE i = 0; i < 4; i++) uuu.c[i] = s[i]; return CondCheck(n, __int64(uuu.w)); } - i = db.cf->filen; if (i > 255)i = 255; + BYTE b[MAX_DBFIELD_LENGTH]; + auto i = db.cf->cfilen; if (i > sizeof(b)) i = sizeof(b); CopyMemory(b, s, i); b[i] = 0; if (!i)return CondCheck(n, b); while (--i)if (b[i] == 0 || b[i] == ' ')b[i] = 0; @@ -2577,15 +2589,15 @@ Column *LOOK::FindFin(short fin) short LOOK::FindCompare(WORD fn) { - char c[512]; + char c[MAX_DBFIELD_LENGTH]; short i, j, L, sBack, lBack, ret; - bool NoWord, YesWholeWords; db.FiNum(fn); L = db.FiDispE(c); ret = 1; if (Yes(FindInvert)) ret = 0; if (Find.Len - Find.nMM > L) goto NOT_FOUND; if (No(FindCaseSens)) if (Yes(WinCode)) CharUpperBuff(c, lstrlen(c)); else FSF.LStrupr(c); - L -= (Find.Len - Find.nMM) - 1; NoWord = false; - YesWholeWords = Yes(WholeWords); + L -= (Find.Len - Find.nMM) - 1; + bool NoWord = false; + bool YesWholeWords = Yes(WholeWords); j = 0; if (Yes(FindReplace)) { j = Find.Pos + Find.Step; @@ -2650,20 +2662,21 @@ short LOOK::FindCompare(WORD fn) short LOOK::ReplaceStr(char *cc) { - char *c, R[512]; - WORD i, j; - db.FiDispE(cc); c = cc + Find.Pos; i = lstrlen(c); - j = lstrlen(Find.RU) - Find.nMMr; + db.FiDispE(cc); + auto c = cc + Find.Pos; + WORD i = lstrlen(c); + WORD j = lstrlen(Find.RU) - Find.nMMr; if (!j) { if (Find.nMMr) return Find.LenF; MoveMemory(c, c + Find.LenF, i - Find.LenF + 1); return 0; } + char R[512]; lstrcpy(R, Find.RU); if (Find.nMMr) { - WORD k, *n; + WORD k; char *r = Find.RU; - n = new WORD[Find.nMMr]; + WORD *n = new WORD[Find.nMMr]; if (j < Find.LenF) { j = Find.LenF - j; while (j)for (k = 0; k < Find.nMMr && j; k++, j--)n[k]++; @@ -2691,7 +2704,7 @@ short LOOK::ReplaceStr(char *cc) short LOOK::Replace() { - char cc[512]; + char cc[MAX_DBFIELD_LENGTH]; short j; j = ReplaceStr(cc); db.SetField(cc); @@ -2742,9 +2755,7 @@ bool LOOK::NotRepl(DWORD rn, short ma = 3) DWORD LOOK::FindNext(short *f, short ma = 3) { - DWORD rn; - Column *c; - rn = recV[curY]; + DWORD rn = recV[curY]; if ((Yes(FindAllFields) && coCurr->Next()) || Yes(FindReplace))--rn; for (;;) { if (++rn > db.dbH.nrec) return 0; @@ -2755,7 +2766,7 @@ DWORD LOOK::FindNext(short *f, short ma = 3) else if (NotRepl(rn, ma)) continue; if (db.Read(rn)) { ShowError(2); return 0; } if (Yes(FindAllFields)) { - c = (Column *) coFirst->Head(); + auto c = (Column *) coFirst->Head(); if (rn == recV[curY]) c = Yes(FindReplace) ? coCurr : (Column *) coCurr->Next(); for (; c; c = (Column *) c->Next()) if (FindCompare(c->finum)) break; if (!c) continue; @@ -2840,7 +2851,7 @@ struct EditDialog { WORD wText; // Maximum width of text line WORD wEdit; // Maximum width of edit line WORD width; // Width of dialog - short iOk; // Index of "Ok" item + short iOk; // Index of "OK" item short iAdd; // Index of "Add" item short iNext; // Index of "Go to next dialog" item short iPrev; // Index of "Go to previous dialog" item @@ -2848,9 +2859,18 @@ struct EditDialog { WORD yLine; // Y for next init line FarDialogItem *di; // Dialog items array - ~EditDialog() { if (di) { delete[] di; di = NULL; } }; + ~EditDialog() { + if (di) { + for (WORD i = 0; i < nItems; i++) { + auto item = di[i]; + if (item.Type == DI_EDIT && (item.Flags & DIF_VAREDIT) != 0 && item.Ptr.PtrData) delete item.Ptr.PtrData; + } + delete[] di; + di = nullptr; + } + }; WORD Init(WORD nL, WORD wT, WORD wE, BYTE but); - short Line(char *t, char *e, short w, const char *mask = NULL); + short Line(const char *t, const char *e, short w, const char *mask = NULL); short Exec(void); }; @@ -2865,11 +2885,11 @@ short EditDialog::Exec(void) return -1; } -short EditDialog::Line(char *t, char *e, short w, const char *mask) +short EditDialog::Line(const char *t, const char *e, short w, const char *mask) { if (iLast == nItems) return 0; di[iLast].Type = DI_TEXT; di[iLast].X1 = 4; di[iLast].Y1 = yLine; - FSF.sprintf(di[iLast].Data, "%*s", wText, t); + FSF.snprintf(di[iLast].Data, sizeof(di[iLast].Data), "%*s", wText, t); ++iLast; di[iLast].X1 = wText + 5; if (yLine == 2) di[iLast].Focus = true; di[iLast].Type = DI_EDIT; if (mask) { @@ -2877,8 +2897,19 @@ short EditDialog::Line(char *t, char *e, short w, const char *mask) di[iLast].Mask = mask; di[iLast].Flags = DIF_MASKEDIT; } - di[iLast].X2 = (w > wEdit) ? wEdit : w; - di[iLast].X2 += di[iLast].X1 - 1; di[iLast].Y1 = yLine; lstrcpy(di[iLast].Data, e); + di[iLast].X2 = w < wEdit ? w + (mask ? 0 : 1) : wEdit; + di[iLast].X2 += di[iLast].X1 - 1; di[iLast].Y1 = yLine; + if (w < 512) // sizeof(FarDialogItem::Data) + { + lstrcpyn(di[iLast].Data, e, 512); + } + else + { + di[iLast].Flags |= DIF_VAREDIT; + di[iLast].Ptr.PtrLength = w + 1; + di[iLast].Ptr.PtrData = new char[di[iLast].Ptr.PtrLength]; + lstrcpyn(di[iLast].Ptr.PtrData, e, di[iLast].Ptr.PtrLength); + } ++iLast; ++yLine; return iLast - 1; } @@ -2923,7 +2954,6 @@ WORD EditDialog::Init(WORD nL, WORD wT, WORD wE, BYTE but) WORD LOOK::EditRecord(void) { short i, j, nL, nD, dL, rL, wT, wE; - char *r, s[384]; BYTE but; Column *c = (Column *) coFirst->Head(); if (db.Read(recV[curY])) { ShowError(2); return 1; } @@ -2948,6 +2978,7 @@ WORD LOOK::EditRecord(void) } c = (Column *) coFirst->Head(); for (i = 0; c; c = (Column *) c->Next()) { + char s[MAX_DBFIELD_LENGTH]; db.FiNum(c->finum); wE = db.FiWidth(); db.FiDispE(s); if (Yes(WinCode) && db.FiChar())ToOem(s); for (j = 0; !j;) { @@ -2971,7 +3002,9 @@ WORD LOOK::EditRecord(void) return 1; } for (c = (Column *) coFirst->Head(); c; c = (Column *) c->Next()) { - db.FiNum(c->finum); r = ed[c->dinum].di[c->idnum].Data; + db.FiNum(c->finum); + auto di = ed[c->dinum].di[c->idnum]; + auto r = (di.Flags & DIF_VAREDIT) != 0 && di.Ptr.PtrData ? di.Ptr.PtrData : di.Data; if (Yes(WinCode) && db.FiChar())ToAlt(r); db.SetField(r); } @@ -3015,7 +3048,7 @@ WORD LOOK::ActualSelected(BYTE a) void LOOK::Clipboard(void) { - char s[512]; + char s[MAX_DBFIELD_LENGTH]; if (db.Read(recV[curY])) { ShowError(2); return; } db.FiNum(coCurr->finum); s[0] = 0; db.FiDisp(s); if (Yes(WinCode) && db.FiChar())ToOem(s); @@ -4030,7 +4063,7 @@ static LONG_PTR WINAPI DiProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) Q = data->GoUp(data->sh >> 2); goto Q_EXEC; case KEY_PGUP: Q = data->GoUp(data->sh - 3); goto Q_EXEC; - case KEY_CTRLPGUP: + case KEY_CTRLPGUP: case KEY_RCTRL | KEY_PGUP: Q = data->GoTop(); goto Q_EXEC; case KEY_DOWN: Q = data->GoDn(1); goto Q_EXEC; @@ -4038,15 +4071,15 @@ static LONG_PTR WINAPI DiProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) Q = data->GoDn(data->sh >> 2); goto Q_EXEC; case KEY_PGDN: Q = data->GoDn(data->sh - 3); goto Q_EXEC; - case KEY_CTRLPGDN: + case KEY_CTRLPGDN: case KEY_RCTRL | KEY_PGDN: Q = data->GoBot(); goto Q_EXEC; - case KEY_CTRLEND: + case KEY_CTRLEND: case KEY_RCTRL | KEY_END: Q = data->GoBot() | data->GoLast(); goto Q_EXEC; case KEY_LEFT: Q = data->GoLeft(); goto Q_EXEC; case KEY_HOME: Q = data->GoFirst(); goto Q_EXEC; - case KEY_CTRLHOME: + case KEY_CTRLHOME: case KEY_RCTRL | KEY_HOME: Q = data->GoTop() | data->GoFirst(); goto Q_EXEC; case KEY_RIGHT: Q = data->GoRight(); goto Q_EXEC; @@ -4167,6 +4200,7 @@ static LONG_PTR WINAPI DiProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) case KEY_ALTF1: // Configure Configure(-1); data->GetConfig(true); + data->InitColumns(); data->KeyShow(); data->ShowStatus(-1); data->ShowPage(); break; diff --git a/src/LookDBF.h b/src/LookDBF.h index d277843..aac83b9 100644 --- a/src/LookDBF.h +++ b/src/LookDBF.h @@ -18,7 +18,7 @@ #define WholeWords 0x00001000 // Whole words only searching #define FindReplace 0x00002000 // Search & replace mode #define ConfReplace 0x00004000 // Replace Confirmation -#define AutoSave 0x00008000 // Tepmlate Autosave +#define AutoSave 0x00008000 // Template auto save #define ExpEmpty 0x00010000 // Export empty file enum { @@ -52,7 +52,7 @@ enum { mImpTitle, mImpFileName, //----------------------- Others mYes, mNo, mAll, mColIns, mSum, mColName, mEditTitle, mTempFile, mGoTo, mTemplate, - //----------------------- Html-taggs + //----------------------- HTML-tags mTabS, mTabF, mTabRowS, mTabRowF, mTabCellS, mTabCellF, mTabSpace }; //=========================================================================== @@ -81,7 +81,7 @@ struct FindData { short Len; // Searching Sample Length short LenF; // Found String Length short nMM; // Number of MultyMask characters in sample - short nMMr; // Number of MultyMask characters in replase substring + short nMMr; // Number of MultyMask characters in replace substring char Mask[2]; // Masking Characters char FD[256]; // Searching Text OEM coding char FU[256]; // Searching Text coding ready for compare @@ -140,11 +140,11 @@ struct LOOK { WORD *S; // Array of record sorted marks dbBase db; // Data Base structure - short LookOnly; // Prohibit edit, append and detete functions + short LookOnly; // Prohibit edit, append and delete functions short MarkOnly; // On/Off marked records only mode of displaying DWORD MarkNum; // Number of marked records DWORD MarkMax; // Maximum number of marked records - short sw, sh; // Screen width and height-1 + WORD sw, sh; // Screen width and height-1 BYTE at[24]; // Colors array short Wrec; // Width of current line number showing short Wcol; // Width of current column number showing @@ -308,6 +308,6 @@ struct LOOK { void DelTemplate(void); int TableSelect(void); int TableSet(int nt); - void ToOem(TCHAR *src, TCHAR *dst = NULL); - void ToAlt(TCHAR *src, TCHAR *dst = NULL); + void ToOem(char *src, char *dst = NULL); + void ToAlt(char *src, char *dst = NULL); }; diff --git a/src/db_use.cpp b/src/db_use.cpp index ad346fd..886b3a0 100644 --- a/src/db_use.cpp +++ b/src/db_use.cpp @@ -15,7 +15,7 @@ void *operator new[](size_t size) {return ::operator new(size); } void *operator new(size_t size, void *p) { return p; } void operator delete[](void *ptr) {::operator delete(ptr); } -//--------- Двухсвязный список объектов --------------- +//--------- Двусвязный список объектов --------------- Link *Link::Head(void) { @@ -176,12 +176,10 @@ char *i64_a(char *s, __int64 val, int mins, int dec) __int64 ah_i64(char *s, __int64 def) { - long z; - char *c; __int64 rez = 0; - for (c = s; *c; c++) { + for (auto c = s; *c; c++) { if (*c < '0') return def; - z = *c - '0'; if (z < 10) goto STORE; + auto z = *c - '0'; if (z < 10) goto STORE; if (*c < 'A') return def; z = *c - 'A' + 10; if (z < 16) goto STORE; if (*c < 'a') return def; @@ -621,11 +619,8 @@ void dbBase::OpenMemo(const char *file, const char *mext) BYTE dbBase::Open(char *file, BYTE ronly) { - WORD k, n, rl; - int lh; - BYTE ret, ind, msk; DWORD nbr; - ret = 0; + BYTE ret = 0; if (f != INVALID_HANDLE_VALUE) return 3; if (!ronly) { f = CreateFile(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, @@ -640,8 +635,8 @@ BYTE dbBase::Open(char *file, BYTE ronly) } if (!ReadFile(f, &dbH, 32, &nbr, NULL) || nbr < 32) return 2; if (dbH.reclen == 0 || dbH.start <= 64 || dbH.nrec < 0) return 2; - dbField *h; - rl = 1; h = NULL, lh = 0; + Link *h = NULL; + WORD rl = 1; int lh = 0; for (nfil = 0;;) { lh += 32; if (lh + 1 > dbH.start) break; @@ -654,19 +649,19 @@ BYTE dbBase::Open(char *file, BYTE ronly) if (d->name[0] == 0x0d) { delete d; break; } if (nbr < 32) goto DB_ERROR; d->loc = rl; - rl += d->filen; - h = (dbField*) (h->Add(d)); + rl += d->cfilen; + h = h->Add(d); nfil++; } if (rl > dbH.reclen) return 2; - k = 0; + WORD k = 0; while (rl < dbH.reclen) { - n = dbH.reclen - rl; if (n > 255)n = 255; + WORD n = dbH.reclen - rl; if (n > 255)n = 255; auto d = new dbField; ZeroMemory(d, sizeof(dbField)); FSF.sprintf(d->name, "#%d#", ++k); d->type = '#'; d->filen = n; - rl += d->filen; - h = (dbField*) (h->Add(d)); + rl += n; + h = h->Add(d); nfil++; } cf = dbF = (dbField*) (h->Head()); @@ -684,7 +679,7 @@ BYTE dbBase::Open(char *file, BYTE ronly) Hext[0] = 0x0d; //-------- _NullFlags field for nullable and variable length fields //-------- recognized and set if it present - ind = 0; msk = 1; Nflg = NULL; + BYTE ind = 0; BYTE msk = 1; Nflg = NULL; for (auto d = dbF; d; d = (dbField*) (d->Next())) { if ((d->spare[0] & 0x05) != 5) continue; if (MyCmp(d->name, "_NullFlags") != 10) continue; @@ -732,7 +727,7 @@ BYTE dbBase::Create(char *file, BYTE t, dbBase *dc) for (d = dbF; d; d = (dbField*) (d->Next())) { d->loc = dbH.reclen; if ((d->spare[0] & 0x05) == 5)nbr = dbH.reclen; - dbH.reclen += d->filen; + dbH.reclen += d->cfilen; dbH.start += 32; } if (dbH.reclen == 1)return 3; @@ -929,7 +924,7 @@ dbField *dbBase::FiNum(WORD n) //=========================================================================== WORD dbBase::FiWidth(void) { - WORD i = cf->filen; + WORD i = cf->cfilen; switch (cf->type) { // case 'D': if(fmtD)i=DTw(fmtD); else i=10; break; case 'D': i = DTw(fmtD); break; @@ -948,9 +943,9 @@ WORD dbBase::FiWidth(void) char *dbBase::FiType(char *s) { - char *c = "%c%3u.%u %s"; + const char *c = "%c%3u.%u %s"; switch (cf->type) { - case 'C': FSF.sprintf(s, c, 'C', cf->filen, cf->dec, "Character"); break; + case 'C': FSF.sprintf(s, "%c%5u %s", 'C', cf->cfilen, "Character"); break; case 'N': FSF.sprintf(s, c, 'N', cf->filen, cf->dec, "Number"); break; case 'D': FSF.sprintf(s, c, 'D', cf->filen, cf->dec, "Date"); break; case 'L': FSF.sprintf(s, c, 'L', cf->filen, cf->dec, "Logical"); break; @@ -1000,11 +995,11 @@ BYTE dbBase::FiNotFull(void) WORD dbBase::FiDisp(char *s, BYTE nll) { - BYTE *c, fle, n; + WORD n; if (!cf)return 0; if (nll && FiNull()) { lstrcpy(s, "Null"); return 4; } - c = rec + cf->loc; - fle = cf->filen; + auto c = rec + cf->loc; + auto fle = cf->cfilen; switch (cf->type) { case 'T': // DateTime if (fle == 8) { // Binary format @@ -1175,15 +1170,15 @@ __int64 dbBase::GetBinary(void) BYTE *dbBase::GetByte(BYTE *s) { - CopyMemory(s, rec + cf->loc, cf->filen); - s[cf->filen] = 0; + CopyMemory(s, rec + cf->loc, cf->cfilen); + s[cf->cfilen] = 0; return s; } //----------------------------------- void dbBase::SetByte(BYTE *s) { - CopyMemory(rec + cf->loc, s, cf->filen); + CopyMemory(rec + cf->loc, s, cf->cfilen); } //----------------------------------- @@ -1197,7 +1192,7 @@ double dbBase::GetDouble(void) sign = 1; j = 0; c = rec + cf->loc; q = 0; - for (i = 0; i < cf->filen; c++, i++) { + for (i = 0; i < cf->cfilen; c++, i++) { if ((*c == ' ') || (*c == '+')) { if (j)break; continue; } if (*c == '-') { if (j)break; sign = -1; continue; } if (*c == '.') { if (j)break; j = 10; continue; } @@ -1290,12 +1285,12 @@ BYTE dbBase::ReWrite(void) void dbBase::SetLeft(char *fval) { WORD i; - for (i = 0; i < cf->filen; i++) { + for (i = 0; i < cf->cfilen; i++) { if (!fval[i]) break; rec[cf->loc + i] = fval[i]; } if (cf->mskV) { - if (i < cf->filen) { rec[cf->loc + cf->filen - 1] = i; SetNotFull(); } + if (i < cf->cfilen) { rec[cf->loc + cf->cfilen - 1] = i; SetNotFull(); } else SetFull(); } } @@ -1307,7 +1302,7 @@ void dbBase::SetRight(char *fval) if (!l) return; l--; int i; - for (i = cf->loc + cf->filen - 1; i >= cf->loc&&l >= 0; i--, l--) rec[i] = fval[l]; + for (i = cf->loc + cf->cfilen - 1; i >= cf->loc&&l >= 0; i--, l--) rec[i] = fval[l]; } //------------------------------- @@ -1318,8 +1313,8 @@ void dbBase::SetEmpty(void) if (cf->type == 'M' || cf->type == '0' || cf->type == 'I' || cf->type == 'B' || cf->type == 'Y' || cf->type == 'G')filler = 0; if (cf->type == 'T'&&cf->filen == 8)filler = 0; - for (WORD i = 0; i < cf->filen; i++) rec[cf->loc + i] = filler; - if (cf->mskV) { rec[cf->loc + cf->filen - 1] = 0; SetNotFull(); } + for (WORD i = 0; i < cf->cfilen; i++) rec[cf->loc + i] = filler; + if (cf->mskV) { rec[cf->loc + cf->cfilen - 1] = 0; SetNotFull(); } } //------------------------------- @@ -1330,7 +1325,7 @@ BYTE dbBase::IsEmpty(void) if (cf->type == 'M' || cf->type == '0' || cf->type == 'I' || cf->type == 'B' || cf->type == 'Y' || cf->type == 'G')filler = 0; if (cf->type == 'T'&&cf->filen == 8)filler = 0; - for (WORD i = 0; i < cf->filen; i++) if (rec[cf->loc + i] != filler) return 0; + for (WORD i = 0; i < cf->cfilen; i++) if (rec[cf->loc + i] != filler) return 0; return 1; } //------------------------------- diff --git a/src/db_use.h b/src/db_use.h index 54af2dc..1948786 100644 --- a/src/db_use.h +++ b/src/db_use.h @@ -1,6 +1,8 @@ #include "stdafx.h" -//--------- Двухсвязный список объектов --------------- +#define MAX_DBFIELD_LENGTH 0x7FFFU + +//--------- Двусвязный список объектов --------------- class Link { Link *prev; @@ -107,6 +109,8 @@ struct dbField :Link { BYTE indN; BYTE mskV; BYTE indV; + WORD getfilen() { return type == 'C' ? filen + (dec << 8) : filen; }; + _declspec(property(get = getfilen)) WORD cfilen; }; struct dbBase { @@ -204,7 +208,7 @@ struct dbBase { // Возвращает 1, если текущее поле переменной длины неполное, иначе 0. BYTE FiNotFull(void); // Преобразует значение поля в читабельный формат в зависимости от - // его типа и помещает в стрку s. Завершает строку нулевым байтом. + // его типа и помещает в строку s. Завершает строку нулевым байтом. // Возвращает длину строки. // Если nll=1 и у поля нет значения (NULL), возвращает строку "Null". // Иначе возвращает содержимое поля, даже если оно помечено как Null. diff --git a/src/version.h b/src/version.h index 8366c05..202f612 100644 --- a/src/version.h +++ b/src/version.h @@ -1,8 +1,8 @@ #include "farversion.hpp" #define PLUGIN_MAJOR_VER 2 -#define PLUGIN_MINOR_VER 7 -#define PLUGIN_BUILD 1 +#define PLUGIN_MINOR_VER 8 +#define PLUGIN_BUILD 0 #define PLUGIN_NAME "LookDBF" #define PLUGIN_FILENAME PLUGIN_NAME ".dll" #define PLUGIN_DESC PLUGIN_NAME " Plugin for Far Manager" diff --git a/whatsnew.eng b/whatsnew.eng index da9785f..49b05c5 100644 --- a/whatsnew.eng +++ b/whatsnew.eng @@ -9,6 +9,12 @@ [-] Error was corrected і use following WebMoney attributes: [*] Changes і WMID:009807013498, Z804712443609, R42074294843 +--------------------------------------------------------------------------- +LookDBF 2.8 - 21.07.2016 +--------------------------------------------------------------------------- +[+] Added support for type 'C' (character) fields longer than 255 symbols +[-] Fixed many buffer overflow bugs related to previous change + --------------------------------------------------------------------------- LookDBF 2.7 - 25.03.2016 --------------------------------------------------------------------------- @@ -29,7 +35,7 @@ LookDBF 2.06 beta. - 18.12.2006 LookDBF 2.05 beta. - 24.08.2006 --------------------------------------------------------------------------- [+] Showing memo-fields is available now for 31h files too - (FoxPro with autoincrement) + (FoxPro with auto-increment) [-] Uncorrectable console resizing (Alt+F9) --------------------------------------------------------------------------- @@ -40,7 +46,7 @@ LookDBF 2.04 beta. - 11.12.2005 in template too. See help topic "Code Tables". [+] PACK function (Ctrl+F2) was added. Remove records with deletion flag. [+] Alt+F8 feature (go to given record number) was extended by functions - Jump Up or Down by given quantyty of records. +N - down by N records. + Jump Up or Down by given quantity of records. +N - down by N records. -N - up by N records. N - go to record number N (as usually). [+] Nullable field support now available. See Help section _NullFlags. [*] Field _NullFlags displayed as hexadecimal now. @@ -78,7 +84,7 @@ LookDBF 2.01 beta - 20.04.2005 --------------------------------------------------------------------------- LookDBF 2.00 beta - 07.04.2005 --------------------------------------------------------------------------- -[+] You may make some plugin parameters permanent now using configuraton +[+] You may make some plugin parameters permanent now using configuration dialog. See Help/Configuration section. [*] Color settings are in configuration dialog now. @@ -93,7 +99,7 @@ LookDBF 2.00 beta - 07.04.2005 search, as in replace string) and in Search by Condition mode. [+] You may change masking characters in Search, Replace and Configuration - dialogs. + dialogs. [+] Search dialog contain inversion now. You may search records that does not contain sample. @@ -102,7 +108,7 @@ LookDBF 2.00 beta - 07.04.2005 conditional search process. See Help/Condition search section. [+] Export dialog was reconstructed. Date and Time formats are added. - Button "Cancel" was changed to "Save epty database". You may cancel dialog + Button "Cancel" was changed to "Save empty database". You may cancel dialog using key ESC or mouse click out of dialog. [+] If you open empty database in edition mode (option /e) you can add empty @@ -130,7 +136,7 @@ LookDBF 1.07 beta - 28.06.2004 [+] Your own mask character for search and replace masking is available now. -[+] Replace is prohibided for fields types D and T if searching and replacing +[+] Replace is prohibited for fields types D and T if searching and replacing strings have different length. [-] Remove bug in marking inversion (Gray *) in "Selected Only" mode. @@ -139,7 +145,7 @@ LookDBF 1.07 beta - 28.06.2004 [+] Export execution time now showed after it. -[-] Trailing blanks are rewoved for current field edition. +[-] Trailing blanks are removed for current field edition. --------------------------------------------------------------------------- LookDBF 1.06 beta - 05.06.2004 @@ -160,7 +166,7 @@ LookDBF 1.05 beta - 27.05.2004 [*] Source text was inspected. All of input-output and memory control functions are changed to standard Win32 API functions. LookDBF now create - its own memory heap, and destory it before closing. + its own memory heap, and destroy it before closing. --------------------------------------------------------------------------- LookDBF 1.04 beta - 20.05.2004 @@ -192,7 +198,7 @@ LookDBF 1.04 beta - 20.05.2004 [+] New key (Ctrl*) is added for NON-actual records marked. -[+] DBF-file import is available now. (Key Shift+F9). See Help for detailes. +[+] DBF-file import is available now. (Key Shift+F9). See Help for details. [+] During export sorting is available now. You can use 3 sorting keys maximum. Sorry, sorting does not fast. @@ -203,13 +209,13 @@ LookDBF 1.04 beta - 20.05.2004 --------------------------------------------------------------------------- LookDBF 1.03 beta - 26.07.2003 --------------------------------------------------------------------------- -[*] Status line rebuilded (see Help). +[*] Status line rebuilt (see Help). [-] Keys Ctrl+PgDn Ё Ctrl+End did not work properly. (It called "algorithm - improwement..." :-))) + improvement..." :-))) [+] Memo-field of Visual FoxPro format added. (DBF-file type 30) and memo-file - extention FPT. + extension FPT. [+] Option /n added into command line. Show records number. @@ -250,15 +256,15 @@ LookDBF 1.02 beta - 20.07.2003 [*] Changed Date and Time edit method. Mask is used now. [+] Memo-field of FoxPro format added. (DBF-file type F5) and memo-file - extention FPT. ( A lot of thanks to Sergey Kovalev for good information, + extension FPT. ( A lot of thanks to Sergey Kovalev for good information, examples and sources). [*] When Memo-field is viewing memo-field name and record number are shown in viewer status line. -[-] Correct buggs with mouse navigation. +[-] Correct bugs with mouse navigation. -[-] Correct buggs with navigation in "Marked Only" mode. +[-] Correct bugs with navigation in "Marked Only" mode. [*] String search dialog changed. @@ -269,7 +275,7 @@ LookDBF 1.02 beta - 20.07.2003 --------------------------------------------------------------------------- LookDBF 1.01 beta - 07.07.2003 --------------------------------------------------------------------------- -[!] Edition functions are prohibided by default. +[!] Edition functions are prohibited by default. [+] New option in command line: /e - edition functions permission. @@ -278,8 +284,8 @@ LookDBF 1.01 beta - 07.07.2003 [+] Sign of edition prohibition "#" added to status line. [+] Read-only files viewing is possible now. In this case edition is - strongly prohibided. -[*] Command line analyse was rewritten. Probably it became better (see Help). + strongly prohibited. +[*] Command line analyze was rewritten. Probably it became better (see Help). [*] Copy to clipboard by Ctrl+C too. Trailing blanks are truncated. @@ -291,7 +297,7 @@ LookDBF 1.01 beta - 07.07.2003 [+] Memo-field viewing added. Only 2 formats of memo are recognized: dBaseIII+ (DBF-file type 83) and dBaseIV (DBF-file type 8b). - Unfortunantely I have not any information about other formats of + Unfortunately I have not any information about other formats of memo-files. If somebody have this information, please, send me it or internet link to it. @@ -307,7 +313,7 @@ LookDBF 1.01 beta - 07.07.2003 [+] New keys AltД and AltД were added for wide fields scrollong. -[*] Colors highliting of active cell have true field length width excluding +[*] Colors highlighting of active cell have true field length width excluding binary fields (such as I, Y etc.) [+] ENTER in fields list (F2) make active this field's column. diff --git a/whatsnew.rus b/whatsnew.rus index a35066d..f19473b 100644 --- a/whatsnew.rus +++ b/whatsnew.rus @@ -9,6 +9,13 @@ [-] €бЇа ў«Ґ­  ®иЁЎЄ  і б®®Ўй о бў®Ё ४ўЁ§Ёвл WebMoney: [*] €§¬Ґ­Ґ­Ёп і WMID:009807013498, Z804712443609, R420742948431 +--------------------------------------------------------------------------- +LookDBF 2.8 - 21.07.2016 +--------------------------------------------------------------------------- +[+] „®Ў ў«Ґ­  Ї®¤¤Ґа¦Є  Ї®«Ґ© вЁЇ  'C' (character) ¤«Ё­­ҐҐ 255 бЁ¬ў®«®ў +[-] €бЇа ў«Ґ­ЁҐ ¬­®¦Ґбвў  ®иЁЎ®Є ЇҐаҐЇ®«­Ґ­Ёп ЎгдҐа , бўп§ ­­ле б ЇаҐ¤л¤г饩 + ¤®а Ў®вЄ®© + --------------------------------------------------------------------------- LookDBF 2.7 - 25.03.2016 ---------------------------------------------------------------------------