View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001043 | Far Manager | Viewer | public | 2009-09-07 22:36 | 2011-04-15 00:37 |
Reporter | theultramage | Assigned To | alexy | ||
Priority | normal | Severity | minor | Reproducibility | N/A |
Status | closed | Resolution | fixed | ||
Product Version | 2.0 | ||||
Fixed in Version | 3.0 | ||||
Summary | 0001043: viewing a file on network share causes 40kB/s network spam of QUERY_PATH_INFO SMB requests | ||||
Description | As $summary$ says. It seems the code, which polls open files for change numerous times per second, and does not distinguish between the local filesystem (says Sysinternals Process Monitor) and remote shares (says Wireshark). | ||||
Additional Information | While it seems like a neat idea, how cpu/hdd intensive is it to do this sort of polling? And isn't there a more efficient event mechanism to replace this polling loop? | ||||
Tags | No tags attached. | ||||
Build | 1934 | ||||
|
[ ] Network drives autorefresh |
|
This setting is unchecked (always was). The bug does not refer to refreshing of folder contents, it refers to nonstop polling for file size(?) while inside the FAR viewer/editor. |
|
Polling for file-size should not occur in the editor, are you sure it happens there as well? |
|
Regarding the viewer, the problem is probably the code below, what this code does is update the viewer when the file is changed - this is what gives far viewer the "tail -f" like feature. A simple solution would be to add a check for a network drive, but I don't really like such a solution as I personaly use this "tail -f" feature on network drives. Another solution can be to set a interval for this polling, I don't know if it is good enough though. case KEY_IDLE: { if(ViewFile) { string strRoot; GetPathRoot(strFullFileName, strRoot); int DriveType=FAR_GetDriveType(strRoot); if (DriveType!=DRIVE_REMOVABLE && !IsDriveTypeCDROM(DriveType)) { FAR_FIND_DATA_EX NewViewFindData; if ( !apiGetFindDataEx (strFullFileName,&NewViewFindData) ) return TRUE; fflush(ViewFile); vseek(ViewFile,0,SEEK_END); __int64 CurFileSize=vtell(ViewFile); if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime || ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime || CurFileSize!=FileSize) { ViewFindData=NewViewFindData; FileSize=CurFileSize; if (FilePos>FileSize) ProcessKey(KEY_CTRLEND); else { __int64 PrevLastPage=LastPage; Show(); if (PrevLastPage && !LastPage) { ProcessKey(KEY_CTRLEND); LastPage=TRUE; } } } } } if (Opt.ViewerEditorClock && HostFileViewer!=NULL && HostFileViewer->IsFullScreen()) ShowTime(FALSE); return(TRUE); } |
|
> Polling for file-size should not occur in the editor, are you sure it happens there as well? Yes, my mistake, only the viewer behaves like this. Some sort of configurable polling period, or an event notification system (if exists) would be preferable. |
|
viewer.diff (5,523 bytes)
Index: viewer.hpp =================================================================== --- viewer.hpp (revision 5887) +++ viewer.hpp (working copy) @@ -163,7 +163,11 @@ bool m_bQuickView; UINT DefCodePage; + int vgetc_ready; + __int64 EOF_Pos; + int update_check_period; + DWORD last_update_check; private: virtual void DisplayObject(); Index: viewer.cpp =================================================================== --- viewer.cpp (revision 5887) +++ viewer.cpp (working copy) @@ -128,6 +128,7 @@ bVE_READ_Sent = false; Signature = false; vgetc_ready = -1; + EOF_Pos = -1; } @@ -376,6 +377,23 @@ ���� �������������� */ CtrlObject->Plugins.ProcessViewerEvent(VE_READ,nullptr); bVE_READ_Sent = true; + + last_update_check = GetTickCount(); + string strRoot; + GetPathRoot(strFullFileName, strRoot); + int DriveType = FAR_GetDriveType(strRoot); + if (IsDriveTypeCDROM(DriveType)) + DriveType = DRIVE_CDROM; + switch (DriveType) //??? make it configurable + { + case DRIVE_REMOVABLE: update_check_period = -1; break; // flash drive or floppy: never + case DRIVE_FIXED: update_check_period = +1; break; // hard disk: 1msec + case DRIVE_REMOTE: update_check_period = 1000; break; // network drive: 1sec + case DRIVE_CDROM: update_check_period = -1; break; // cd/dvd: never + case DRIVE_RAMDISK: update_check_period = +1; break; // ramdrive: 1msec + default: update_check_period = -1; break; // unknown: never + } + return TRUE; } @@ -454,7 +472,11 @@ if (!SelectSize) SelectPos=FilePos; - switch (nMode) + __int64 last_filepos = -1; + bool eof_mode = EOF_Pos >= 0 && nMode == SHOW_RELOAD; + do { + + switch (nMode) { case SHOW_HEX: CtrlObject->Plugins.CurViewer = this; //HostFileViewer; @@ -473,6 +495,13 @@ ReadString(Strings[I],-1,MAX_VIEWLINEB); } + if (eof_mode) + { + last_filepos = vtell(); + eof_mode = last_filepos < EOF_Pos; + if (eof_mode) + nMode = SHOW_DOWN; + } break; case SHOW_UP: @@ -506,8 +535,20 @@ ReadString(Strings[Y2-Y1],-1,MAX_VIEWLINEB); Strings[Y2-Y1]->nFilePos = vtell(); ReadString(Strings[Y2-Y1],-1,MAX_VIEWLINEB); + + if (eof_mode) + { + __int64 fpos = vtell(); + if (fpos >= EOF_Pos || fpos <= last_filepos) + { + eof_mode = false; nMode = SHOW_RELOAD; + } + else + last_filepos = fpos; + } break; } + } while ( eof_mode ); if (nMode != SHOW_HEX) { @@ -676,7 +717,7 @@ if (!X) { - *OutStr=0; + *OutStr = L'\0'; break; } @@ -721,7 +762,7 @@ if (!nr) { - *OutStr=0; + *OutStr = L'\0'; } else { @@ -816,7 +857,7 @@ if (!X) { - *OutStr=0; + *OutStr = L'\0'; break; } @@ -1269,42 +1310,39 @@ } case KEY_IDLE: { - if (ViewFile.Opened()) + if (ViewFile.Opened() && update_check_period >= 0) { - string strRoot; - GetPathRoot(strFullFileName, strRoot); - int DriveType=FAR_GetDriveType(strRoot); + DWORD now_ticks = GetTickCount(); + if ((int)(now_ticks - last_update_check) < update_check_period) + return TRUE; + last_update_check = now_ticks; - if (DriveType!=DRIVE_REMOVABLE && !IsDriveTypeCDROM(DriveType)) - { - FAR_FIND_DATA_EX NewViewFindData; + FAR_FIND_DATA_EX NewViewFindData; + if (!apiGetFindDataEx(strFullFileName, NewViewFindData)) + return TRUE; - if (!apiGetFindDataEx(strFullFileName, NewViewFindData)) - return TRUE; + ViewFile.FlushBuffers(); + vseek(0,SEEK_END); + __int64 CurFileSize=vtell(); - ViewFile.FlushBuffers(); - vseek(0,SEEK_END); - __int64 CurFileSize=vtell(); + if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime + || ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime + || CurFileSize!=FileSize) + { + ViewFindData=NewViewFindData; + FileSize=CurFileSize; - if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime || - ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime || - CurFileSize!=FileSize) + if (FilePos>FileSize) + ProcessKey(KEY_CTRLEND); + else { - ViewFindData=NewViewFindData; - FileSize=CurFileSize; + __int64 PrevLastPage=LastPage; + Show(); - if (FilePos>FileSize) + if (PrevLastPage && !LastPage) + { ProcessKey(KEY_CTRLEND); - else - { - __int64 PrevLastPage=LastPage; - Show(); - - if (PrevLastPage && !LastPage) - { - ProcessKey(KEY_CTRLEND); - LastPage=TRUE; - } + LastPage=TRUE; } } } @@ -1796,6 +1834,8 @@ } FilePos=vtell(); + if (!VM.Hex && VM.Wrap && VM.WordWrap) + EOF_Pos = FilePos; //!!! hack to adjust possible incorrect last page show /* { @@ -1826,6 +1866,7 @@ } */ Show(); + EOF_Pos = -1; // LastSelPos=FilePos; } |
|
можно например так... в аттаче 2 апдэйта (1043, 796). периоды опроса пока просто зашиты в код - для DRIVE_REMOTE: один раз в секунду ЗЫ: должны быть табы в индентах (viewer.diff) ... |
|
viewer_10.diff (16,011 bytes)
Index: viewer.hpp =================================================================== --- viewer.hpp (revision 5894) +++ viewer.hpp (working copy) @@ -163,7 +163,11 @@ bool m_bQuickView; UINT DefCodePage; + int vgetc_ready; + __int64 EOF_Pos; + int update_check_period; + DWORD last_update_check; private: virtual void DisplayObject(); Index: cache.cpp =================================================================== --- cache.cpp (revision 5894) +++ cache.cpp (working copy) @@ -128,30 +128,39 @@ { INT64 Pointer=0; Pointer = file.GetPointer(); - bool Bidirection=false; - if(Pointer>BufferSize/2) + + int shift = (int)Pointer & 0x7ff; // 2k pointer alignment for \\.\CdRom0 + if (Pointer-shift > BufferSize/2) + shift += BufferSize/2; // suppose BufferSize/2 is 2k aligned... + + if (shift) + file.SetPointer(-shift, nullptr, FILE_CURRENT); + + DWORD read_size = BufferSize; + UINT64 FileSize = 0; + if (file.GetSize(FileSize) && Pointer-shift+BufferSize > (INT64)FileSize) + read_size = (DWORD)((INT64)FileSize-Pointer+shift); + + Result = file.Read(Buffer, read_size, ReadSize); + if (Result) { - Bidirection=true; - file.SetPointer(-BufferSize/2, nullptr, FILE_CURRENT); - } - Result = file.Read(Buffer, BufferSize, ReadSize); - if(Result) - { - BytesLeft = ReadSize; - if(Bidirection && BytesLeft>=BufferSize/2) + if (ReadSize > (DWORD)shift) { - BytesLeft-=BufferSize/2; + BytesLeft = ReadSize - shift; + file.SetPointer(Pointer, nullptr, FILE_BEGIN); } - file.SetPointer(Pointer, nullptr, FILE_BEGIN); + else + BytesLeft = 0; } else { - if (Bidirection) + if (shift) file.SetPointer(Pointer, nullptr, FILE_BEGIN); ReadSize=0; BytesLeft=0; } } + return Result; } Index: viewer.cpp =================================================================== --- viewer.cpp (revision 5894) +++ viewer.cpp (working copy) @@ -128,6 +128,7 @@ bVE_READ_Sent = false; Signature = false; vgetc_ready = -1; + EOF_Pos = -1; } @@ -376,6 +377,31 @@ ���� �������������� */ CtrlObject->Plugins.ProcessViewerEvent(VE_READ,nullptr); bVE_READ_Sent = true; + + last_update_check = GetTickCount(); + string strRoot; + GetPathRoot(strFullFileName, strRoot); + int DriveType = FAR_GetDriveType(strRoot); + if (IsDriveTypeCDROM(DriveType)) + DriveType = DRIVE_CDROM; + switch (DriveType) //??? make it configurable + { + case DRIVE_REMOVABLE: update_check_period = -1; break; // flash drive or floppy: never + case DRIVE_FIXED: update_check_period = +1; break; // hard disk: 1msec + case DRIVE_REMOTE: update_check_period = 1000; break; // network drive: 1sec + case DRIVE_CDROM: update_check_period = -1; break; // cd/dvd: never + case DRIVE_RAMDISK: update_check_period = +1; break; // ramdrive: 1msec + default: update_check_period = -1; break; // unknown: never + } + + // �������� �� ���� ����� ���������� ������� ������: + // \\.\C: \\.\D: \\.\PhysucalDrive0 \\.\CdRom0 .... + if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFullFileName)) + { + DWORD dummy; + ViewFile.IoControl(FSCTL_ALLOW_EXTENDED_DASD_IO, NULL,0, NULL,0, &dummy); + } + return TRUE; } @@ -454,7 +480,11 @@ if (!SelectSize) SelectPos=FilePos; - switch (nMode) + __int64 last_filepos = -1; + bool eof_mode = EOF_Pos >= 0 && nMode == SHOW_RELOAD; + do { + + switch (nMode) { case SHOW_HEX: CtrlObject->Plugins.CurViewer = this; //HostFileViewer; @@ -473,6 +503,13 @@ ReadString(Strings[I],-1,MAX_VIEWLINEB); } + if (eof_mode) + { + last_filepos = vtell(); + eof_mode = last_filepos < EOF_Pos; + if (eof_mode) + nMode = SHOW_DOWN; + } break; case SHOW_UP: @@ -506,8 +543,20 @@ ReadString(Strings[Y2-Y1],-1,MAX_VIEWLINEB); Strings[Y2-Y1]->nFilePos = vtell(); ReadString(Strings[Y2-Y1],-1,MAX_VIEWLINEB); + + if (eof_mode) + { + __int64 fpos = vtell(); + if (fpos >= EOF_Pos || fpos <= last_filepos) + { + eof_mode = false; nMode = SHOW_RELOAD; + } + else + last_filepos = fpos; + } break; } + } while ( eof_mode ); if (nMode != SHOW_HEX) { @@ -598,7 +647,6 @@ wchar_t OutStr[MAX_VIEWLINE],TextStr[20]; int EndFile; __int64 SelSize; - WCHAR Ch; int X,Y,TextPos; int SelStart, SelEnd; bool bSelStartFound = false, bSelEndFound = false; @@ -640,93 +688,80 @@ const wchar_t BorderLine[]={BoxSymbols[BS_V1],L' ',0}; + int out_len = (int)wcslen(OutStr); + int border_len = (int)wcslen(BorderLine); + if (IsUnicodeCodePage(VM.CodePage)) { - for (X=0; X<8; X++) + wchar_t line[8]; + int nr = vread(line, 8); + LastPage = EndFile = ViewFile.Eof() ? 1 : 0; + if (nr <= 0) { - __int64 fpos = vtell(); - - if (SelectSize>0 && (SelectPos == fpos)) + *OutStr = L'\0'; + } + else + { + for (X=0; X<8; X++) { - bSelStartFound = true; - SelStart = (int)wcslen(OutStr); - SelSize=SelectSize; - /* $ 22.01.2001 IS - ��������! ��������, ��� �� ������ ������ ������ ������� - ������� �� ��������, �� ��� ���� ������� � ������ �� �����. - � ���������� SelectSize ��� � Process* - */ - //SelectSize=0; - } - - if (SelectSize>0 && (fpos == (SelectPos+SelectSize-1))) - { - bSelEndFound = true; - SelEnd = (int)wcslen(OutStr)+3; - SelSize=SelectSize; - } - - if (!vgetc(Ch)) - { - /* $ 28.06.2000 tran - ������� ����� ������ ������, ���� ����� - ����� ������ 16 */ - EndFile=1; - LastPage=1; - - if (!X) + if (SelectSize>0 && (SelectPos == fpos)) { - *OutStr=0; - break; + bSelStartFound = true; + SelStart = (int)wcslen(OutStr); + SelSize=SelectSize; } - - wcscat(OutStr,L" "); - TextStr[TextPos++]=L' '; - } - else - { - WCHAR OutChar=Ch; - - if (VM.CodePage == CP_REVERSEBOM) + if (SelectSize>0 && (fpos == (SelectPos+SelectSize-1))) { - _swab(reinterpret_cast<LPSTR>(&OutChar),reinterpret_cast<LPSTR>(&OutChar),sizeof(WCHAR)); + bSelEndFound = true; + SelEnd = (int)wcslen(OutStr)+3; + SelSize=SelectSize; } - int OutStrLen=StrLength(OutStr); - _snwprintf(OutStr+OutStrLen,ARRAYSIZE(OutStr)-OutStrLen,L"%02X%02X ",HIBYTE(OutChar),LOBYTE(OutChar)); - - if (!Ch) + if (X < nr) { - Ch=L' '; + unsigned char b1 = HIBYTE(line[X]), b2 = LOBYTE(line[X]); +#if 0 // !!! ��������� �������� !!! + if (VM.CodePage != CP_REVERSEBOM) // ��� ������ � ���� ���� + { // ������� �������� ������������� ��� + unsigned char t = b1; b1 = b2; b2 = t; + } +#endif + _snwprintf(OutStr+out_len, ARRAYSIZE(OutStr)-out_len, L"%02X%02X ", b1, b2); + TextStr[TextPos++] = line[X] ? line[X] : L' '; } + else + { + wcscpy(OutStr+out_len, L" "); + TextStr[TextPos++] = L' '; + } + out_len += 5; - TextStr[TextPos++]=Ch; - LastPage=0; + if (X == 3) + { + wcscpy(OutStr+out_len, BorderLine); + out_len += border_len; + } } - - if (X==3) - wcscat(OutStr, BorderLine); + ++fpos; } } - else if ( CP_UTF8 == VM.CodePage ) + else { - __int64 fpos = vtell(); unsigned char line[16+3]; DWORD nr = 0; - Reader.Read(line, (DWORD)sizeof(line), &nr); + DWORD nb = CP_UTF8 == VM.CodePage ? 16+3 : 16; + Reader.Read(line, nb, &nr); if (nr > 16) Reader.Unread(nr-16); - LastPage = nr < (DWORD)sizeof(line) && ViewFile.Eof() ? 1 : 0; + LastPage = EndFile = (nr <= nb) && ViewFile.Eof() ? 1 : 0; if (!nr) { - *OutStr=0; + *OutStr = L'\0'; } else { - int out_len = (int)wcslen(OutStr); - int border_len = (int)wcslen(BorderLine); if (SelectSize) { if (SelectPos >= fpos && SelectPos < fpos+16) @@ -755,95 +790,37 @@ else wcscpy(OutStr+off, L" "); TextStr[X] = L' '; + if (CP_UTF8 != VM.CodePage && X < (int)nr && line[X]) + MultiByteToWideChar(VM.CodePage, 0, (LPCSTR)line+X, 1, TextStr+X, 1); } - wchar_t w1[16], w2[16]; - int tail, nw, ib=0, iw=0; - nw = utf8_to_WideChar((char *)line, (int)nr, w1, w2, 16, tail); - bool first = true; - while (ib < 16 && iw < nw) + if (CP_UTF8 == VM.CodePage) { - if (first && w1[iw] == REPLACE_CHAR && w2[iw] == L'?') + wchar_t w1[16], w2[16]; + int tail, nw, ib=0, iw=0; + nw = utf8_to_WideChar((char *)line, (int)nr, w1, w2, 16, tail); + bool first = true; + while (ib < 16 && iw < nw) { - TextStr[ib++] = CONTINUE_CHAR; // ��� ����� �� �� ������ ��������� �� '����' utf-8 - } // �� ������� ��-�� ����� ��� �� ��� ���� �� �����... - else - { - first = false; - TextStr[ib++] = w1[iw] ? w1[iw] : L' '; + if (first && w1[iw] == REPLACE_CHAR && w2[iw] == L'?') + { + TextStr[ib++] = CONTINUE_CHAR; // ��� ����� �� �� ������ ��������� �� '����' utf-8 + } // �� ������� ��-�� ����� ��� �� ��� ���� �� �����... + else + { + first = false; + TextStr[ib++] = w1[iw] ? w1[iw] : L' '; + } + int clen = WideCharToMultiByte(CP_UTF8, 0, w2+iw, 1, NULL,0, NULL,NULL); + while (--clen > 0 && ib < 16) + TextStr[ib++] = CONTINUE_CHAR; + ++iw; } - int clen = WideCharToMultiByte(CP_UTF8, 0, w2+iw, 1, NULL,0, NULL,NULL); - while (--clen > 0 && ib < 16) - TextStr[ib++] = CONTINUE_CHAR; - ++iw; } TextPos = 16; } } - else - { - for (X=0; X<16; X++) - { - __int64 fpos = vtell(); - if (SelectSize>0 && (SelectPos == fpos)) - { - bSelStartFound = true; - SelStart = (int)wcslen(OutStr); - SelSize=SelectSize; - /* $ 22.01.2001 IS - ��������! ��������, ��� �� ������ ������ ������ ������� - ������� �� ��������, �� ��� ���� ������� � ������ �� �����. - � ���������� SelectSize ��� � Process* - */ - //SelectSize=0; - } - - if (SelectSize>0 && (fpos == (SelectPos+SelectSize-1))) - { - bSelEndFound = true; - SelEnd = (int)wcslen(OutStr)+1; - SelSize=SelectSize; - } - - if (!vgetc(Ch)) - { - /* $ 28.06.2000 tran - ������� ����� ������ ������, ���� ����� - ����� ������ 16 */ - EndFile=1; - LastPage=1; - - if (!X) - { - *OutStr=0; - break; - } - - /* $ 03.07.2000 tran - - ������ 5 �������� ��� ���� 3 */ - wcscat(OutStr,L" "); - TextStr[TextPos++]=L' '; - } - else - { - char NewCh; - WideCharToMultiByte(VM.CodePage, 0, &Ch,1, &NewCh,1," ",nullptr); - int OutStrLen=StrLength(OutStr); - _snwprintf(OutStr+OutStrLen,ARRAYSIZE(OutStr)-OutStrLen,L"%02X ", NewCh); - - if (!Ch) - Ch=L' '; - - TextStr[TextPos++]=Ch; - LastPage=0; - } - - if (X==7) - wcscat(OutStr,BorderLine); - } - } - TextStr[TextPos]=0; wcscat(TextStr,L" "); @@ -1269,42 +1246,39 @@ } case KEY_IDLE: { - if (ViewFile.Opened()) + if (ViewFile.Opened() && update_check_period >= 0) { - string strRoot; - GetPathRoot(strFullFileName, strRoot); - int DriveType=FAR_GetDriveType(strRoot); + DWORD now_ticks = GetTickCount(); + if ((int)(now_ticks - last_update_check) < update_check_period) + return TRUE; + last_update_check = now_ticks; - if (DriveType!=DRIVE_REMOVABLE && !IsDriveTypeCDROM(DriveType)) - { - FAR_FIND_DATA_EX NewViewFindData; + FAR_FIND_DATA_EX NewViewFindData; + if (!apiGetFindDataEx(strFullFileName, NewViewFindData)) + return TRUE; - if (!apiGetFindDataEx(strFullFileName, NewViewFindData)) - return TRUE; + ViewFile.FlushBuffers(); + vseek(0,SEEK_END); + __int64 CurFileSize=vtell(); - ViewFile.FlushBuffers(); - vseek(0,SEEK_END); - __int64 CurFileSize=vtell(); + if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime + || ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime + || CurFileSize!=FileSize) + { + ViewFindData=NewViewFindData; + FileSize=CurFileSize; - if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime || - ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime || - CurFileSize!=FileSize) + if (FilePos>FileSize) + ProcessKey(KEY_CTRLEND); + else { - ViewFindData=NewViewFindData; - FileSize=CurFileSize; + __int64 PrevLastPage=LastPage; + Show(); - if (FilePos>FileSize) - ProcessKey(KEY_CTRLEND); - else + if (PrevLastPage && !LastPage) { - __int64 PrevLastPage=LastPage; - Show(); - - if (PrevLastPage && !LastPage) - { - ProcessKey(KEY_CTRLEND); - LastPage=TRUE; - } + ProcessKey(KEY_CTRLEND); + LastPage=TRUE; } } } @@ -1785,7 +1759,17 @@ unsigned int max_counter=Y2-Y1; if (VM.Hex) + { vseek(0,SEEK_END); + FilePos = vtell(); + int line_chars = IsUnicodeCodePage(VM.CodePage) ? 8 : 16; + if ((FilePos % line_chars) == 0) + FilePos -= line_chars * (Y2 - Y1 + 1); + else + FilePos -= (FilePos % line_chars) + line_chars * (Y2 - Y1); + if (FilePos < 0) + FilePos = 0; + } else { vseek(-1,SEEK_END); @@ -1793,39 +1777,17 @@ if (vgetc(LastSym) && LastSym!=CRSym) ++max_counter; - } - FilePos=vtell(); + FilePos=vtell(); + if (VM.Wrap && VM.WordWrap) + EOF_Pos = FilePos; //!!! hack to adjust possible incorrect last page show - /* - { - char Buf[100]; - sprintf(Buf,"%I64X",FilePos); - Message(0,1,"End",Buf,"Ok"); - } - */ - for (int i=0; static_cast<unsigned int>(i)<max_counter; i++) - Up(); + for (int i=0; static_cast<unsigned int>(i)<max_counter; i++) + Up(); + } - /* - { - char Buf[100]; - sprintf(Buf,"%I64X, %d",FilePos, I); - Message(0,1,"Up",Buf,"Ok"); - } - */ - if (VM.Hex) - FilePos&=~(IsUnicodeCodePage(VM.CodePage) ? 0x7:0xf); - - /* - if (VM.Hex) - { - char Buf[100]; - sprintf(Buf,"%I64X",FilePos); - Message(0,1,"VM.Hex",Buf,"Ok"); - } - */ Show(); + EOF_Pos = -1; // LastSelPos=FilePos; } @@ -3003,14 +2965,12 @@ } } - int Viewer::vseek(__int64 Offset,int Whence) { vgetc_ready = -1; return ViewFile.SetPointer(Offset*(IsUnicodeCodePage(VM.CodePage)?2:1), nullptr, Whence); } - __int64 Viewer::vtell() { INT64 Ptr=ViewFile.GetPointer(); @@ -3021,7 +2981,6 @@ return Ptr; } - bool Viewer::vgetc(WCHAR& C) { bool Result; @@ -3059,7 +3018,6 @@ return Result; } - #define RB_PRC 3 #define RB_HEX 4 #define RB_DEC 5 |
|
viewer_10.diff содержит все мои незакоммиченные изменения для вьювера. не только для 1043, но также фиксы для hex-view и просмотра спец-файлов (\\.\C: \\.\PhysicalDrive0 .....) Просто для этих багов соответствующие мантисы закрыты... изменения для фар2 как обычно: http://sharapov-16.narod.ru/far/index.html |
|
> int shift = (int)Pointer & 0x7ff; // 2k pointer alignment for \\.\CdRom0 У новых жестких дисков сектора по 4k. |
|
не знал... поправлю viewer_11.diff -- выравнивание позиционирования на 4k |
|
кстати, раз мы читаем по 64к, может быть и прыгать имеет смысл на 64к-границу? При рандомном листании читаться будут всё время одни и те же куски и (теоретически) ос может это как-то кешировать и оптимизировать. |
|
viewer_11.diff (16,055 bytes)
Index: viewer.hpp =================================================================== --- viewer.hpp (revision 5894) +++ viewer.hpp (working copy) @@ -163,7 +163,11 @@ bool m_bQuickView; UINT DefCodePage; + int vgetc_ready; + __int64 EOF_Pos; + int update_check_period; + DWORD last_update_check; private: virtual void DisplayObject(); Index: cache.cpp =================================================================== --- cache.cpp (revision 5894) +++ cache.cpp (working copy) @@ -128,30 +128,39 @@ { INT64 Pointer=0; Pointer = file.GetPointer(); - bool Bidirection=false; - if(Pointer>BufferSize/2) + + int shift = (int)Pointer & 0xfff; // 4k pointer alignment (some new disks has 4k sector size) + if (Pointer-shift > BufferSize/2) + shift += BufferSize/2; // suppose BufferSize/2 is 4k aligned... + + if (shift) + file.SetPointer(-shift, nullptr, FILE_CURRENT); + + DWORD read_size = BufferSize; + UINT64 FileSize = 0; + if (file.GetSize(FileSize) && Pointer-shift+BufferSize > (INT64)FileSize) + read_size = (DWORD)((INT64)FileSize-Pointer+shift); + + Result = file.Read(Buffer, read_size, ReadSize); + if (Result) { - Bidirection=true; - file.SetPointer(-BufferSize/2, nullptr, FILE_CURRENT); - } - Result = file.Read(Buffer, BufferSize, ReadSize); - if(Result) - { - BytesLeft = ReadSize; - if(Bidirection && BytesLeft>=BufferSize/2) + if (ReadSize > (DWORD)shift) { - BytesLeft-=BufferSize/2; + BytesLeft = ReadSize - shift; + file.SetPointer(Pointer, nullptr, FILE_BEGIN); } - file.SetPointer(Pointer, nullptr, FILE_BEGIN); + else + BytesLeft = 0; } else { - if (Bidirection) + if (shift) file.SetPointer(Pointer, nullptr, FILE_BEGIN); ReadSize=0; BytesLeft=0; } } + return Result; } Index: viewer.cpp =================================================================== --- viewer.cpp (revision 5894) +++ viewer.cpp (working copy) @@ -128,6 +128,7 @@ bVE_READ_Sent = false; Signature = false; vgetc_ready = -1; + EOF_Pos = -1; } @@ -376,6 +377,31 @@ ���� �������������� */ CtrlObject->Plugins.ProcessViewerEvent(VE_READ,nullptr); bVE_READ_Sent = true; + + last_update_check = GetTickCount(); + string strRoot; + GetPathRoot(strFullFileName, strRoot); + int DriveType = FAR_GetDriveType(strRoot); + if (IsDriveTypeCDROM(DriveType)) + DriveType = DRIVE_CDROM; + switch (DriveType) //??? make it configurable + { + case DRIVE_REMOVABLE: update_check_period = -1; break; // flash drive or floppy: never + case DRIVE_FIXED: update_check_period = +1; break; // hard disk: 1msec + case DRIVE_REMOTE: update_check_period = 1000; break; // network drive: 1sec + case DRIVE_CDROM: update_check_period = -1; break; // cd/dvd: never + case DRIVE_RAMDISK: update_check_period = +1; break; // ramdrive: 1msec + default: update_check_period = -1; break; // unknown: never + } + + // �������� �� ���� ����� ���������� ������� ������: + // \\.\C: \\.\D: \\.\PhysucalDrive0 \\.\CdRom0 \\?\Volume{Volume_GUID} ... + if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFullFileName)) + { + DWORD dummy; + ViewFile.IoControl(FSCTL_ALLOW_EXTENDED_DASD_IO, NULL,0, NULL,0, &dummy); + } + return TRUE; } @@ -454,7 +480,11 @@ if (!SelectSize) SelectPos=FilePos; - switch (nMode) + __int64 last_filepos = -1; + bool eof_mode = EOF_Pos >= 0 && nMode == SHOW_RELOAD; + do { + + switch (nMode) { case SHOW_HEX: CtrlObject->Plugins.CurViewer = this; //HostFileViewer; @@ -473,6 +503,13 @@ ReadString(Strings[I],-1,MAX_VIEWLINEB); } + if (eof_mode) + { + last_filepos = vtell(); + eof_mode = last_filepos < EOF_Pos; + if (eof_mode) + nMode = SHOW_DOWN; + } break; case SHOW_UP: @@ -506,8 +543,20 @@ ReadString(Strings[Y2-Y1],-1,MAX_VIEWLINEB); Strings[Y2-Y1]->nFilePos = vtell(); ReadString(Strings[Y2-Y1],-1,MAX_VIEWLINEB); + + if (eof_mode) + { + __int64 fpos = vtell(); + if (fpos >= EOF_Pos || fpos <= last_filepos) + { + eof_mode = false; nMode = SHOW_RELOAD; + } + else + last_filepos = fpos; + } break; } + } while ( eof_mode ); if (nMode != SHOW_HEX) { @@ -598,7 +647,6 @@ wchar_t OutStr[MAX_VIEWLINE],TextStr[20]; int EndFile; __int64 SelSize; - WCHAR Ch; int X,Y,TextPos; int SelStart, SelEnd; bool bSelStartFound = false, bSelEndFound = false; @@ -640,93 +688,80 @@ const wchar_t BorderLine[]={BoxSymbols[BS_V1],L' ',0}; + int out_len = (int)wcslen(OutStr); + int border_len = (int)wcslen(BorderLine); + if (IsUnicodeCodePage(VM.CodePage)) { - for (X=0; X<8; X++) + wchar_t line[8]; + int nr = vread(line, 8); + LastPage = EndFile = ViewFile.Eof() ? 1 : 0; + if (nr <= 0) { - __int64 fpos = vtell(); - - if (SelectSize>0 && (SelectPos == fpos)) + *OutStr = L'\0'; + } + else + { + for (X=0; X<8; X++) { - bSelStartFound = true; - SelStart = (int)wcslen(OutStr); - SelSize=SelectSize; - /* $ 22.01.2001 IS - ��������! ��������, ��� �� ������ ������ ������ ������� - ������� �� ��������, �� ��� ���� ������� � ������ �� �����. - � ���������� SelectSize ��� � Process* - */ - //SelectSize=0; - } - - if (SelectSize>0 && (fpos == (SelectPos+SelectSize-1))) - { - bSelEndFound = true; - SelEnd = (int)wcslen(OutStr)+3; - SelSize=SelectSize; - } - - if (!vgetc(Ch)) - { - /* $ 28.06.2000 tran - ������� ����� ������ ������, ���� ����� - ����� ������ 16 */ - EndFile=1; - LastPage=1; - - if (!X) + if (SelectSize>0 && (SelectPos == fpos)) { - *OutStr=0; - break; + bSelStartFound = true; + SelStart = (int)wcslen(OutStr); + SelSize=SelectSize; } - - wcscat(OutStr,L" "); - TextStr[TextPos++]=L' '; - } - else - { - WCHAR OutChar=Ch; - - if (VM.CodePage == CP_REVERSEBOM) + if (SelectSize>0 && (fpos == (SelectPos+SelectSize-1))) { - _swab(reinterpret_cast<LPSTR>(&OutChar),reinterpret_cast<LPSTR>(&OutChar),sizeof(WCHAR)); + bSelEndFound = true; + SelEnd = (int)wcslen(OutStr)+3; + SelSize=SelectSize; } - int OutStrLen=StrLength(OutStr); - _snwprintf(OutStr+OutStrLen,ARRAYSIZE(OutStr)-OutStrLen,L"%02X%02X ",HIBYTE(OutChar),LOBYTE(OutChar)); - - if (!Ch) + if (X < nr) { - Ch=L' '; + unsigned char b1 = HIBYTE(line[X]), b2 = LOBYTE(line[X]); +#if 0 // !!! ��������� �������� !!! + if (VM.CodePage != CP_REVERSEBOM) // ��� ������ � ���� ���� + { // ������� �������� ������������� ��� + unsigned char t = b1; b1 = b2; b2 = t; + } +#endif + _snwprintf(OutStr+out_len, ARRAYSIZE(OutStr)-out_len, L"%02X%02X ", b1, b2); + TextStr[TextPos++] = line[X] ? line[X] : L' '; } + else + { + wcscpy(OutStr+out_len, L" "); + TextStr[TextPos++] = L' '; + } + out_len += 5; - TextStr[TextPos++]=Ch; - LastPage=0; + if (X == 3) + { + wcscpy(OutStr+out_len, BorderLine); + out_len += border_len; + } } - - if (X==3) - wcscat(OutStr, BorderLine); + ++fpos; } } - else if ( CP_UTF8 == VM.CodePage ) + else { - __int64 fpos = vtell(); unsigned char line[16+3]; DWORD nr = 0; - Reader.Read(line, (DWORD)sizeof(line), &nr); + DWORD nb = CP_UTF8 == VM.CodePage ? 16+3 : 16; + Reader.Read(line, nb, &nr); if (nr > 16) Reader.Unread(nr-16); - LastPage = nr < (DWORD)sizeof(line) && ViewFile.Eof() ? 1 : 0; + LastPage = EndFile = (nr <= nb) && ViewFile.Eof() ? 1 : 0; if (!nr) { - *OutStr=0; + *OutStr = L'\0'; } else { - int out_len = (int)wcslen(OutStr); - int border_len = (int)wcslen(BorderLine); if (SelectSize) { if (SelectPos >= fpos && SelectPos < fpos+16) @@ -755,95 +790,37 @@ else wcscpy(OutStr+off, L" "); TextStr[X] = L' '; + if (CP_UTF8 != VM.CodePage && X < (int)nr && line[X]) + MultiByteToWideChar(VM.CodePage, 0, (LPCSTR)line+X, 1, TextStr+X, 1); } - wchar_t w1[16], w2[16]; - int tail, nw, ib=0, iw=0; - nw = utf8_to_WideChar((char *)line, (int)nr, w1, w2, 16, tail); - bool first = true; - while (ib < 16 && iw < nw) + if (CP_UTF8 == VM.CodePage) { - if (first && w1[iw] == REPLACE_CHAR && w2[iw] == L'?') + wchar_t w1[16], w2[16]; + int tail, nw, ib=0, iw=0; + nw = utf8_to_WideChar((char *)line, (int)nr, w1, w2, 16, tail); + bool first = true; + while (ib < 16 && iw < nw) { - TextStr[ib++] = CONTINUE_CHAR; // ��� ����� �� �� ������ ��������� �� '����' utf-8 - } // �� ������� ��-�� ����� ��� �� ��� ���� �� �����... - else - { - first = false; - TextStr[ib++] = w1[iw] ? w1[iw] : L' '; + if (first && w1[iw] == REPLACE_CHAR && w2[iw] == L'?') + { + TextStr[ib++] = CONTINUE_CHAR; // ��� ����� �� �� ������ ��������� �� '����' utf-8 + } // �� ������� ��-�� ����� ��� �� ��� ���� �� �����... + else + { + first = false; + TextStr[ib++] = w1[iw] ? w1[iw] : L' '; + } + int clen = WideCharToMultiByte(CP_UTF8, 0, w2+iw, 1, NULL,0, NULL,NULL); + while (--clen > 0 && ib < 16) + TextStr[ib++] = CONTINUE_CHAR; + ++iw; } - int clen = WideCharToMultiByte(CP_UTF8, 0, w2+iw, 1, NULL,0, NULL,NULL); - while (--clen > 0 && ib < 16) - TextStr[ib++] = CONTINUE_CHAR; - ++iw; } TextPos = 16; } } - else - { - for (X=0; X<16; X++) - { - __int64 fpos = vtell(); - if (SelectSize>0 && (SelectPos == fpos)) - { - bSelStartFound = true; - SelStart = (int)wcslen(OutStr); - SelSize=SelectSize; - /* $ 22.01.2001 IS - ��������! ��������, ��� �� ������ ������ ������ ������� - ������� �� ��������, �� ��� ���� ������� � ������ �� �����. - � ���������� SelectSize ��� � Process* - */ - //SelectSize=0; - } - - if (SelectSize>0 && (fpos == (SelectPos+SelectSize-1))) - { - bSelEndFound = true; - SelEnd = (int)wcslen(OutStr)+1; - SelSize=SelectSize; - } - - if (!vgetc(Ch)) - { - /* $ 28.06.2000 tran - ������� ����� ������ ������, ���� ����� - ����� ������ 16 */ - EndFile=1; - LastPage=1; - - if (!X) - { - *OutStr=0; - break; - } - - /* $ 03.07.2000 tran - - ������ 5 �������� ��� ���� 3 */ - wcscat(OutStr,L" "); - TextStr[TextPos++]=L' '; - } - else - { - char NewCh; - WideCharToMultiByte(VM.CodePage, 0, &Ch,1, &NewCh,1," ",nullptr); - int OutStrLen=StrLength(OutStr); - _snwprintf(OutStr+OutStrLen,ARRAYSIZE(OutStr)-OutStrLen,L"%02X ", NewCh); - - if (!Ch) - Ch=L' '; - - TextStr[TextPos++]=Ch; - LastPage=0; - } - - if (X==7) - wcscat(OutStr,BorderLine); - } - } - TextStr[TextPos]=0; wcscat(TextStr,L" "); @@ -1269,42 +1246,39 @@ } case KEY_IDLE: { - if (ViewFile.Opened()) + if (ViewFile.Opened() && update_check_period >= 0) { - string strRoot; - GetPathRoot(strFullFileName, strRoot); - int DriveType=FAR_GetDriveType(strRoot); + DWORD now_ticks = GetTickCount(); + if ((int)(now_ticks - last_update_check) < update_check_period) + return TRUE; + last_update_check = now_ticks; - if (DriveType!=DRIVE_REMOVABLE && !IsDriveTypeCDROM(DriveType)) - { - FAR_FIND_DATA_EX NewViewFindData; + FAR_FIND_DATA_EX NewViewFindData; + if (!apiGetFindDataEx(strFullFileName, NewViewFindData)) + return TRUE; - if (!apiGetFindDataEx(strFullFileName, NewViewFindData)) - return TRUE; + ViewFile.FlushBuffers(); + vseek(0,SEEK_END); + __int64 CurFileSize=vtell(); - ViewFile.FlushBuffers(); - vseek(0,SEEK_END); - __int64 CurFileSize=vtell(); + if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime + || ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime + || CurFileSize!=FileSize) + { + ViewFindData=NewViewFindData; + FileSize=CurFileSize; - if (ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime || - ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime || - CurFileSize!=FileSize) + if (FilePos>FileSize) + ProcessKey(KEY_CTRLEND); + else { - ViewFindData=NewViewFindData; - FileSize=CurFileSize; + __int64 PrevLastPage=LastPage; + Show(); - if (FilePos>FileSize) - ProcessKey(KEY_CTRLEND); - else + if (PrevLastPage && !LastPage) { - __int64 PrevLastPage=LastPage; - Show(); - - if (PrevLastPage && !LastPage) - { - ProcessKey(KEY_CTRLEND); - LastPage=TRUE; - } + ProcessKey(KEY_CTRLEND); + LastPage=TRUE; } } } @@ -1785,7 +1759,17 @@ unsigned int max_counter=Y2-Y1; if (VM.Hex) + { vseek(0,SEEK_END); + FilePos = vtell(); + int line_chars = IsUnicodeCodePage(VM.CodePage) ? 8 : 16; + if ((FilePos % line_chars) == 0) + FilePos -= line_chars * (Y2 - Y1 + 1); + else + FilePos -= (FilePos % line_chars) + line_chars * (Y2 - Y1); + if (FilePos < 0) + FilePos = 0; + } else { vseek(-1,SEEK_END); @@ -1793,39 +1777,17 @@ if (vgetc(LastSym) && LastSym!=CRSym) ++max_counter; - } - FilePos=vtell(); + FilePos=vtell(); + if (VM.Wrap && VM.WordWrap) + EOF_Pos = FilePos; //!!! hack to adjust possible incorrect last page show - /* - { - char Buf[100]; - sprintf(Buf,"%I64X",FilePos); - Message(0,1,"End",Buf,"Ok"); - } - */ - for (int i=0; static_cast<unsigned int>(i)<max_counter; i++) - Up(); + for (int i=0; static_cast<unsigned int>(i)<max_counter; i++) + Up(); + } - /* - { - char Buf[100]; - sprintf(Buf,"%I64X, %d",FilePos, I); - Message(0,1,"Up",Buf,"Ok"); - } - */ - if (VM.Hex) - FilePos&=~(IsUnicodeCodePage(VM.CodePage) ? 0x7:0xf); - - /* - if (VM.Hex) - { - char Buf[100]; - sprintf(Buf,"%I64X",FilePos); - Message(0,1,"VM.Hex",Buf,"Ok"); - } - */ Show(); + EOF_Pos = -1; // LastSelPos=FilePos; } @@ -3003,14 +2965,12 @@ } } - int Viewer::vseek(__int64 Offset,int Whence) { vgetc_ready = -1; return ViewFile.SetPointer(Offset*(IsUnicodeCodePage(VM.CodePage)?2:1), nullptr, Whence); } - __int64 Viewer::vtell() { INT64 Ptr=ViewFile.GetPointer(); @@ -3021,7 +2981,6 @@ return Ptr; } - bool Viewer::vgetc(WCHAR& C) { bool Result; @@ -3059,7 +3018,6 @@ return Result; } - #define RB_PRC 3 #define RB_HEX 4 #define RB_DEC 5 |
|
рандомное чтение для просмотра скорее исключение, чем правило. а при последовательном чтении поведение не изменится. я думаю овчинка не стоит выделки (если конечно 'совсем новые' диски не появятся с секторами по 64к :) |
|
вообще-то кроме жёстких дисков существует куча всякой экзотики. закладыватся на то, что сектор будет всегда не более чем 4k мне кажется неправильным. |
|
Можно и конфигурить... (причем сначала размер буфера, а потом выравнивание) Но вообще 4к - это уже размер страницы памяти (в типичном случае). В msdn было еще упоминание и о выравнивании буфера, на размер сектора. Но почему-то работает и без этого (возможно я просто читал старую статью). Пока страница 4к - можно не заморачиваться (IMHO). И кстати у флэш-драйвов 'сектор' больше чем 4к, но работать будет... Я надеюсь (кстати кто-нибудь проверял?) |
|
Можно же через GetDiskFreeSpace получить размер кластера. Типа как в FTP: static unsigned get_cluster_size(const char *fname) { char root[MAX_PATH]; if(GetFullPathName(fname, ARRAYSIZE(root), root, NULL) && root[1] == ':' && root[2] == '\\') { DWORD t1, t2, bps = 0, spc = 0; root[3] = '\0'; spc = bps = 0; if(GetDiskFreeSpace(root, &spc, &bps, &t1, &t2)) return(spc*bps); } return(0); } |
|
Не уверен, что прокатит. Но что-нибудь вроде DeviceIoControl(GET_DRIVE_GEOMETRY...) работать будет (имя приблизительное). |
|
> Пока страница 4к вообще-то существовали windows со страницей 8k. |
|
1934 |
|
1934 |
|
я же написал (в типичном случае). nix-ы c 8k страницами и сейчас не редкость... но это так треп, я согласен - закладываться на 4к не стоит. код который проверяет размер сектора я уже написал - работает, но попутно я правлю вьювер - пока не закончил (надоело разбирать код, решил переписать up/down). хотел закончить с этим сегодня... не успел |
|
общий патч: http://bugs.farmanager.com/view.php?id=1031#bugnotes |
Date Modified | Username | Field | Change |
---|---|---|---|
2009-09-07 22:36 | theultramage | New Issue | |
2009-09-08 00:51 | zg | Note Added: 0004032 | |
2009-09-08 01:36 | theultramage | Note Added: 0004034 | |
2009-09-08 01:37 | theultramage | Note Edited: 0004034 | |
2009-09-08 22:35 | alexy | Note Added: 0004050 | |
2009-09-08 22:50 | alexy | Note Added: 0004051 | |
2009-09-09 23:56 | theultramage | Note Added: 0004058 | |
2010-02-15 17:09 | alexy | Category | File System => Viewer |
2010-02-15 17:09 | alexy | Summary | opening file on network share causes 40kB/s network spam of QUERY_PATH_INFO SMB requests => viewing a file on network share causes 40kB/s network spam of QUERY_PATH_INFO SMB requests |
2010-02-16 07:59 | alexy | Status | new => assigned |
2010-02-16 07:59 | alexy | Assigned To | => alexy |
2011-03-26 08:51 | 2useven10 | File Added: viewer.diff | |
2011-03-26 08:55 | 2useven10 | Note Added: 0006567 | |
2011-03-26 08:57 | 2useven10 | Note Edited: 0006567 | |
2011-03-26 09:07 | 2useven10 | Note Edited: 0006567 | |
2011-03-27 00:05 | 2useven10 | File Added: viewer_10.diff | |
2011-03-27 00:09 | 2useven10 | Note Added: 0006569 | |
2011-03-27 00:10 | 2useven10 | Note Edited: 0006569 | |
2011-03-27 00:10 | 2useven10 | Note Edited: 0006569 | |
2011-03-27 00:11 | 2useven10 | Note Edited: 0006569 | |
2011-03-27 08:21 | DrKnS | Note Added: 0006570 | |
2011-03-27 09:17 | 2useven10 | Note Added: 0006572 | |
2011-03-27 09:32 | DrKnS | Note Added: 0006574 | |
2011-03-27 09:36 | 2useven10 | File Added: viewer_11.diff | |
2011-03-27 09:38 | 2useven10 | Note Edited: 0006572 | |
2011-03-27 09:41 | 2useven10 | Note Added: 0006575 | |
2011-03-27 10:46 | zg | Note Added: 0006577 | |
2011-03-27 14:28 | 2useven10 | Note Added: 0006578 | |
2011-03-27 14:35 | 2useven10 | Note Edited: 0006578 | |
2011-03-27 14:41 | alexy | Note Added: 0006579 | |
2011-03-27 14:51 | 2useven10 | Note Added: 0006580 | |
2011-03-27 19:26 | zg | Note Added: 0006581 | |
2011-03-27 21:56 | alexy | Note Added: 0006582 | |
2011-03-27 21:56 | alexy | Status | assigned => feedback |
2011-03-27 21:56 | alexy | Note Added: 0006583 | |
2011-03-27 22:36 | 2useven10 | Note Added: 0006585 | |
2011-03-30 09:17 | 2useven10 | Note Added: 0006640 | |
2011-04-15 00:37 | alexy | Build | => 1934 |
2011-04-15 00:37 | alexy | Status | feedback => closed |
2011-04-15 00:37 | alexy | Resolution | open => fixed |
2011-04-15 00:37 | alexy | Fixed in Version | => 3.0 |